Обновить

Комментарии 18

Самое веселье начинается в шейдерах. Например, если говорить о WebGL, то там целое число high precision integer на десктопе 32 разрядное, 4 байтное, т.е. до 4,294,967,296 , а вот на мобильных устройствах целое является 24 разрядным, т.е. до 16,777,216. И нигде про это не написано, нащупал методом граблей.

А прямо задаваемых типов нет? В C ведь придумали uint32_t и подобные и избежали неоднозначности между архитектурами.

Прямо такого нет. В шейдерах задаются int & float. Кроме того, можно вначале шейдера объявить точность таким вот образом:

precision highp int;

precision highp float;

float a;

Это означает, что для типа int & float будет использоваться максимально возможная точность. Только вот на разном железе она разная. На десктопах это int32, на мобильных устройствах int24.

Вообще-то это вот эта страница Эрика.
https://0.30000000000000004.com

И ещё — всего две функции — плюс н минус показаны. Где умножение, деление, где сравнение, т.к. с числами с плавающей запятой разлижные правила математики не работают, например X + Y иногда не равно Y + X. Не говоря уже об Y * (B * C) и (A * B) * C.

Так-же и правило малых чисел стоит упомянуть, как например этот пример и что из него будет:
1.5 × 10^20 + 100.5

Очень часто проверка на ноль может не работать.

почти наверняка там где получилось 0.30..04 все операции будут работать одинаково

А еще сложение в числах с плавающей запятой коммутативно, т.е. X + Y всегда равно Y + X (но не ассоциативно) (ну и если не брать в расчет NaN+NaN)

Поэтому если надо просуммировать кучу чисел примерно одного порядка, не надо делать это наивным методом, т.е. объявить переменную и прибавлять к ней слагаемые по одному

Проверка на ноль в мире float/double не работает ± всегда. Первое правило - задать достаточную в рамках задачи точность eps, в пределах которой два числа считаются равными. Правда тут начинаются интересности со сложением чисел с сильно разными порядками.

В самом интересном случае можно одним exe на двух компах получить в зоне "обычных" значение идентичные результаты, а в зоне, приближающейся к краю диапазона (~10^-20 для float) разницу в порядок-другой.

Проверка на ноль в мире float/double не работает ± всегда.

Проверка на ноль работает всегда! Это компьютер. В первую очередь нужно уяснить для себя, что вы подразумеваете под этой проверкой на ноль. И когда требуется проверить именно на содержание нуля, а не бесконечно малого числа - это всегда работает.

Вторая проблема это когда вы задаете этот самый фиксированный EPS, то автоматически отсекаете возможный диапазон решений на более малый числах, когда текущая порядковая точность это позволяет. В этом и суть плавающего числа. А если вам нужен EPS, то подозреваю вам не плавающие числа нужны, а числа с фиксированной точкой.

А можно ещё пример в COBOL, если это возможно?

Как говорится, конец немного предсказуем. Кто-нибудь знает язык, который бы для вычислений с плавающей запятой не использовал сопроцессор? Или хоть одну причину чтобы использовать такой язык?

Все БД вовсе не используют плавающую запятую (возможность такая есть, обычно, но я не встречал в реальной жизни). У нас в системе приложены титанические усилия, что бы все вычисления проводились над типами с фиксированной точностью - ибо финансовые вычисления, и флоаты для них смерть. Вот и причина.

Ну БД просто по умолчанию старается в numeric, но float там есть, да и по примерам выше это видно.

НЛО прилетело и опубликовало эту надпись здесь

Дроби это маленькая часть чисел с плавающей запятой. То, что ограничивается числами типа x.yz, легко решается путем перехода данных "от рублей к копейкам". Для операций со всем остальным приходится мириться, что не только данные представляются неточно, но и результат операций тоже вычисляется неточно. Ну, и конечно, a+b+c начинает зависеть от порядка вычислений.

Был баг на проде, где из файла читали целое в строке 13 и парсили в double получалось 12.999… и потом уже приводили к int. Жуткая штука

В C# меня бесит, что стандартный вывод плавающих чисел идёт через запятую, а стандартный парсинг - через точку. Идиотизм.

Насколько я знаю, зависит от локали системы, а не захардкожено.

только сегодня столкнулся с "подарком" от вычислений с плавающей точкой.
Нужно было запускать расчеты толщины пластины с разной точность. Использован был numpy.

import numpy as np
np.arange(0.1, 0.5, 0.1) # array([0.1, 0.2, 0.3, 0.4]) 
np.arange(0.6, 1.1, 0.1) # array([0.6, 0.7, 0.8, 0.9, 1. , 1.1])
np.arange(0.6, 1.0, 0.1) # array([0.6, 0.7, 0.8, 0.9])
np.arange(1.6, 2.1, 0.1) # array([1.6, 1.7, 1.8, 1.9, 2. ])
np.arange(0.6, 1.2, 0.1) # array([0.6, 0.7, 0.8, 0.9, 1. , 1.1])

Строка 2 нормальное логичное поведение из парадигмы питона, не учитывать последний элемента

Строка 3, ....

Строка 4,кажется что разработчики ненавидят цифру 1

Строка 5, почему не совпадает с 3!?

Строка 6, почему совпадает с 3!?

Мне кажется 3 и 4й примеры работы прекрасны. Разработчики numpy похожу что в курсе и в документации об этом как бы сказано(мне кажется это повод удалить саму функцию или запретить использование для float, а не писать что поведение ну типа странное).

Да, понимаю что float не так прост, но почему библиотека которая позиционирует себя как что-то для работы с точными вычислениями, такое выдает!? И вы еще боритесь за написание кода высокой культуры? Сколько скрытых ошибок благодаря такому поведению кода можно ожидать?

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Информация

Сайт
myoffice.ru
Дата регистрации
Дата основания
2013
Численность
1 001–5 000 человек
Местоположение
Россия
Представитель
vvanomad