Подводные камни PHP

123
D
На сайте с 05.06.2007
Offline
155
#11

myhand, вам не кажется уже смешным ставить кругом колы и двойки как в школе? Вы ведь тоже не всегда правы. Или вы работаете учителем? Прежде чем оспаривать чужое мнение, нужно суметь вникнуть в суть которую пытается донести человек, даже если он (для вас) неправильно выразился, а уже потом солить свой приговор.

По теме:

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

И то что это нельзя сделать более правильным математически, тем более не убедили.

С каких пор мир подстраивается под программирование, а не наоборот?

Вывод из этого только один, не доверять ceil и floor, а также использовать round после операций с такими числами...

Дальше можно не обсуждать, всё и так предельно ясно.

Написал не мало шедевров ;)
M
На сайте с 16.09.2009
Offline
278
#12
Dimanych:
myhand, вам не кажется уже смешным ставить кругом колы и двойки как в школе?

Развивайте чувство юмора :)

Dimanych:
Вы меня не убедили в том что так как сейчас работает, это правильно и так и должно быть.

А как должно? Весь конфуз у Вас от непонимания того, что для внутреннего представления чисел с плавающей точкой - таки используется основание 2. Соответственно, неизбежно округление при преобразовании между системами с разными основаниями. В частности, и для основания 10.

Dimanych:
И то что это нельзя сделать более правильным математически, тем более не убедили.

Boris A Dolgov совершенно правильно заметил - повторите школьный материал ;)

Dimanych:
Вывод из этого только один, не доверять ceil и floor, а также использовать round после операций с такими числами...

"Вывод" из этого совершенно другой. Разобраться что такое за зверь "арифметика чисел с плавающей точкой". Не путайте это с арифметикой действительных чисел - тут много чего может не работать: сложение и умножение не обязательно ассоциативны или дистрибутивны.

http://en.wikipedia.org/wiki/Floating_point

Кнут, т.II

IEEE 754

Используйте арифметику произвольной точности, наконец. BCMath - вообще стандартная библиотека PHP.

Абонементное сопровождение серверов (Debian) Отправить личное сообщение (), написать письмо ().
_vb_
На сайте с 25.07.2009
Offline
104
#13
Dimanych:

С каких пор мир подстраивается под программирование, а не наоборот?

Вы напрасно кипятитесь, вам совершенно правильно сказали:

myhand:
Весь конфуз у Вас от непонимания того, что для внутреннего представления чисел с плавающей точкой - таки используется основание 2.

Дело не в зловредных программистах, а в системе исчисления. Может на примере понятнее будет.

В десятичной системе нельзя предстваить без потери точности 1/3 = 0.333333...

В двоичной - те числа, знаменатели которых не являются степенью двойки, например 1/5 = 0.2

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

и да, эта проблема не php. она присутствует во всех языках - и в питоне, и в си, и в ассемблере.

Саратовская фракция серча (). Давайте посчитаемся.
D
На сайте с 05.06.2007
Offline
155
#14

Систему я уже давно понял, мне не понятно вот что:

Почему при любом выводе выводится целое число, а при использовании floor ceil int возникают погрешности, почему бы не проводить операцию над целым числом, тем что выдаёт echo? Как я вообще могу увидеть именно то что в памяти находится? 1019.9999999999

$x=10.2*100;

var_dump($x);

> float(1020)

printf("%f",$x);

> 1020.000000

var_dump((int)$x);

> int(1019)

Может быть так будет понятным, вот не вижу я тут никаких 9ток, округление не правильное. :)

Всё таки считаю в этом моменте есть баг, да ещё какой!

Может быть вам просто не хочется вдумываться глубоко, вы считате что в PHP не может быть таких багов и вы сразу выносите приговор? :)

M
На сайте с 16.09.2009
Offline
278
#15
Dimanych:
почему бы не проводить операцию над целым числом, тем что выдаёт echo?

Повторяем два раза и меедленно. echo выдает не "целое число" - оно печатает цифры в строке. Поняли?

Dimanych:
Как я вообще могу увидеть именно то что в памяти находится?

gdb?

Ну а var_dump() покажет Вам только тип объекта в памяти.

Dimanych:
Может быть так будет понятным, вот не вижу я тут никаких 9ток, округление не правильное. :)

Домашнее задание.

1) Перевести 1020 в двоичную систему счисления.

2) Представить это число в формате с плавающей точкой.

3) Округлить.

4) Перевести результат в десятичную систему

Справитесь? Покажите что получилось на этапах 1)-4).

Boris A Dolgov
На сайте с 04.07.2007
Offline
215
#16
Dimanych:
Систему я уже давно понял, мне не понятно вот что:
Почему при любом выводе выводится целое число, а при использовании floor ceil int возникают погрешности, почему бы не проводить операцию над целым числом, тем что выдаёт echo? Как я вообще могу увидеть именно то что в памяти находится? 1019.9999999999

$x=10.2*100;
var_dump($x);
> float(1020)

printf("%f",$x);
> 1020.000000

var_dump((int)$x);
> int(1019)

Может быть так будет понятным, вот не вижу я тут никаких 9ток, округление не правильное. :)
Всё таки считаю в этом моменте есть баг, да ещё какой!
Может быть вам просто не хочется вдумываться глубоко, вы считате что в PHP не может быть таких багов и вы сразу выносите приговор? :)

Уже писали выше - из-за округления при отображении. Попробуйте вывести printf("%.100f",$x), если пхп так умеет.

С уважением, Борис Долгов. Администрирование, дешевые лицензии ISPsystem, Parallels, cPanel, DirectAdmin, скины, SSL - ISPlicense.ru (http://www.isplicense.ru/?from=4926)
D
На сайте с 05.06.2007
Offline
155
#17

Точно, ладно проехали, спасибо за разъяснение)

$x=10.2*100;

printf("%.100f",$x);

1019.9999999999998863131622783839702606201172

printf("%.100f",0.2);

0.2000000000000000111022302462515654042363

printf("%.100f",2);

2.0000000000000000000000000000000000000000

rtyug
На сайте с 13.05.2009
Offline
263
#18

Dimanych, интересно, зачем Вам нужна такая точность?

где-то была таблица в которой были перечислены все модули с конкретной точностью для каждого ЯП

вариант:

perl -M'Math::Round qw(:all)' -e 'print round_even(10.30*100)'

rtyug добавил 10-02-2011 в 23:37

вот таблица, но это не та, тут мало, только встроенные:

Round_functions_in_programming_languages

Спалил тему: Pokerstars вывод WMZ, etc на VISA 0% или SWIFT + Конверт USD/GBP,etc (net profit $0,5 млрд) (https://minfin.com.ua/blogs/94589307/115366/) Monobank - 50₴ на счет при рег. тут (https://clck.ru/DLX4r) | Номер SIP АТС Москва 7(495) - 0Ꝑ, 8(800) - 800Ꝑ/0Ꝑ (http://goo.gl/XOrCSn)
D
На сайте с 05.06.2007
Offline
155
#19

Мне такая точность не нужна, мне нужно было для денежной суммы выполнить floor(), на случай если более 2 знаков после запятой, например

10.209 => 10.20

но не как не укладывался в голове такой результат

10.20 => 10.19

особенно когда это происходило очень редко :)

rtyug
На сайте с 13.05.2009
Offline
263
#20

можете по гуглить про "банковское округление"

по-моиму round_even - это и есть оно, хотя точно не знаю

там это в каком-то стандарте записано...

123

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