PHP иногда неправильно считает одни и те же числа?

12
FFFFx029A
На сайте с 01.09.2007
Offline
142
#11
Оптимизайка:
Поэтому в финансовых системах деньги хранят в целых числах (в копейках) т.е., чтоб не терялись ;)

Так а как хранить в копейках? Допустим мне пришло число 11.5, допустим уберу по хитрому запятую и 115 умножу на 10, выйдет 1115, далее мне например нужно вырезать с этого числа 70% и потом от этих 70% вырезать ещё 10%, далее отнять это от основной суммы и результаты распихнуть в 3 ячейки. (ну это алгоритм типичной партнёрки с рефами, цифры конечно же разные могут быть)

Так вот как ни крути, получается что выходят дробные числа.

Так вот если всё что ниже копейки не важно, то при расчётах можно делать intval(float) или он может выдать Nan? И опять же при выходе и входе ВСЁ РАВНО дробные числа выходят и гипотетически при конвертации 123000 в 12.3 может выйти этот Nan?

Или всётаки с типом данных DECIMAL(19,2) можно смело делать подсчёты, всё норм будет сохранятся а базу и глюк (NaN) может быть только с числами близкими к нулю?

И можно ли как-то конвертить числа NaN в нормальное дробное число?

---------- Добавлено 30.06.2016 в 16:55 ----------

VHS:
Храни в целых числах [x], показывай как хочешь - [x] / 100(1000, 10000)...
А версия mysql какая?

Тут неплохо разжевано все
http://tarlyun.com/blog/2011/03/22/xranenie-ne-celyx-chisel-v-mysql/

Версия sql 5.1.66-0+squeeze1

Так в принципе и с типом данных decimal(19,2) нормально сохраняет дроби, ну покайнемере у меня с типом FLOAT была ошибка в том, что вместо нуля (2.15-2.15), сохраняло в базу -4.4408920985006E-16, а вот после исправления типа данных с float на decimal(19,2), это дело норм сохранило и записало 0 (может с другими цифрами будут нюансы, не знаю).

Но далее у меня идут другие вычисления с дробными числами, которые точно будут больше 0 и мне их потом скорее всего придётся записывать в файл, ну и не хотелось бы чтоб выходили Nan числа. ИЛи Nan только с числами близкими к нулю могут быть? Вообще как-то культурно "фильтровать" т.е конвертить NaN в float можно? Я уже совсем запутался.

Зараннее спасибо за ответ.

http://www.youtube.com/watch?v=Gyl4E4EcPdc (http://www.youtube.com/watch?v=Gyl4E4EcPdc) - партнёрка от Мавроди и МММ))) http://miniwm.ru/soft.php?read=917 (http://miniwm.ru/soft.php?read=917) CMS MiniWM v2.8 - 49.99$
VHS
На сайте с 28.09.2007
Offline
142
VHS
#12

Ну если не поможет, что я написал выше, то в php используй is_nan(), и приводи к 0 такие числа. Хотя если собрать все в кучу и смоделировать свою задачу - выход найдется очень быстро.

Ну а вообще nan должно вылезать только в результатах некорректных действий с математическими функциями, типа acos(8), а так же при подстановке в вычисления НЕ_чисел. В остальных случаях проблем быть не должно. Это я про вычисления. У тебя же ошибка была в типе хранения данных и особенностей хранения float.

FFFFx029A
На сайте с 01.09.2007
Offline
142
#13
VHS:
Ну если не поможет, что я написал выше, то в php используй is_nan(), и приводи к 0 такие числа. Хотя если собрать все в кучу и смоделировать свою задачу - выход найдется очень быстро.

Ну а вообще nan должно вылезать только в результатах некорректных действий с математическими функциями, типа acos(8), а так же при подстановке в вычисления НЕ_чисел. В остальных случаях проблем быть не должно.

Так у меня при простом отнимании такое вышло т.е NaN, получается 2.15-2.15=-4.4408920985006E-16

первое число было достато из базы, а второе число вышло в результате 5.4-3.25=2.15, при этом если 0+2.15, то выходит 2.15, также пробывал 1+2.15 тоже норм, ещё пробывал (2.15-2.15=-4.4408920985006E-)+1=1

Поидее еслиб 2.15 было не число, то при прибавлении 1 или 0, выходилабы билиберда, а оно всё норм считает. Вообще первый раз такую аномалию обнаружил на ровном месте.. 🙅

И вот только что ещё затестил:

round((2.15-2.15),2)=-0

2.15-2.15=-4.4408920985006E-16

Получается и округлить не вышло. Как вообще лучше пофиксить такие дела?

VHS
На сайте с 28.09.2007
Offline
142
VHS
#14

Еще раз - 2,15 - ты видел в phpmyadmin (представление), а по факту десятичная часть хранилась в виде степени 2, и если твое число не имеет точного результата - хранится округленное значение. Поэтому ошибки при ручном вводе 2,15 небыло. Другими словами, представь, что высчитываешь 2,15-2,150000000000000000000004.

По ссылке посмотри, какие результаты записываются в базу в тип float при простейших операциях.

FFFFx029A
На сайте с 01.09.2007
Offline
142
#15
VHS:
Еще раз - 2,15 - ты видел в phpmyadmin (представление), а по факту десятичная часть хранилась в виде степени 2, и если твое число не имеет точного результата - хранится округленное значение. Поэтому ошибки при ручном вводе 2,15 небыло. Другими словами, представь, что высчитываешь 2,15-2,150000000000000000000004.

Ну я примерно понял что там где-то спрятаны ещё циферки.. А как пофиксить такой результат?

ООО, вот буквально только что решил вопрос "красиво":

round((round(2.15,2)-round(2.15,2)),2)=0;

Ух, аж как гора с плеч. Оно кстате в ненужную сторону врядле округлит? (из 2.15 не выйдет 2.14 или 2.16?) А эт, может ещё как-то можно пофиксить?

И round() часом не выдаст NaN в самый неподходящий момент?

VHS
На сайте с 28.09.2007
Offline
142
VHS
#16

Нет, округление по правилам. 3 знак >=5, значит вверх, иначе вниз. Но проще хранить в decimal или int, тогда в вычисления изначально не будут поступать кривые значения. А округления и преобразования делать перед записью.

FFFFx029A
На сайте с 01.09.2007
Offline
142
#17
VHS:
Нет, округление по правилам. 3 знак >=5, значит вверх, иначе вниз. Но проще хранить в decimal или int, тогда в вычисления изначально не будут поступать кривые значения. А округления и преобразования делать перед записью.

Ну у меня сейчас вроде везде округляется всё где теоретически может быть дальше 0.01, эт вовремя этот баг нашел, ещё не сразу понял где подвох, думал я что-то пропустил, хотя по сути такой нюанс и пропустил..

Спасибо Вам! 🚬

12

Авторизуйтесь или зарегистрируйтесь, чтобы оставить комментарий