Комментарии 109
А у нас в офисе висит настоящий бубен (кожанный такой с погремушками железными). Правда он почему-то не помогает =)
+2
PHP 5.2.2
Бубен не работает.
Бубен не работает.
0
$value[0] = 97.5;
$value[1] = (9.975-9)*100;
if(($value[0])==$value[1]){echo «TRUE»;}else{echo «FALSE»;}
Вернуло FALSE, эм… чё-то я затупил…
$value[1] = (9.975-9)*100;
if(($value[0])==$value[1]){echo «TRUE»;}else{echo «FALSE»;}
Вернуло FALSE, эм… чё-то я затупил…
0
Не стоит вообще полагаться на точность после умножения float'ов. Ежели уж где-то совсем никак юзать sprinf для удаления шлака в неинтересующих порядках. Например если var_dump'ать round(sprintf('%f',$value)) то наверное всё одинаково выведется.
+14
Угу, это в мануале написано большими красными буквами: ru.php.net/float
+17
actionscript 2.0
97.5, 98
97.5, 97
actionscript 3.0
97.5, 98
97.49999999999997,97
хм…
97.5, 98
97.5, 97
actionscript 3.0
97.5, 98
97.49999999999997,97
хм…
+2
Все правильно. Нужно учесть внутренее представление вещественных чисел в компьютере. Мантисса всегда содержит какую-то маленькую ошибку, в процессе проведения операций эти ошибки могут накапливаться.
(9.975-9)*100 это на самом деле 97.499999999999972, и оно должно округлиться именно до 97 по правилам округления чисел.
(9.975-9)*100 это на самом деле 97.499999999999972, и оно должно округлиться именно до 97 по правилам округления чисел.
+18
смею предположить, что в PHP реализовано статистическое округление, и в отличии от математического, статистическое поочередно округляет 0,5 в разные стороны, то до 0, то до 1.
-10
Как это в математических операциях не математическое округление? Ошибка в мантиссе — это самое правдоподобное объяснение. Сами с этим сталкивались не раз, приходилось вводить некоторые не очень естественные ограничения.
+4
Т.е. round(0.5) иногда равен 0, а иногда 1? Простите, но как его тогда использовать? Если мне нужно случайное поведение — я использую random, а отнюдь не round.
+2
Помимо математического существуют ещё и другие виды округления:
- • банковское — округление половины (N+1 знак = 5) к ближайшему чётному. В этом случае исчезает систематическая ошибка округления при суммировании большого количества чисел.
- • статистическое округление
- • округление к большему, округление к +∞ (англ. ceil) — если у числа округляемые знаки не равны нулю, число округляется в большую сторону. Эту форму округления используют при расчётах с потребителями сотовые операторы связи, провайдеры интернет.
- • округление к меньшему, округление к −∞ (англ. floor) — если у числа округляемые знаки не равны нулю, то число округляется в меньшую сторону (в случае положительных чисел округляемые знаки отбрасываются, в случае отрицательных чисел значение числа увеличивается по модулю).
- • округление к большему по модулю (округление к бесконечности, округление от нуля) относительно редко используемая форма округления, представляет из себя симметричную версию «округления к большему».
- • округление к меньшему по модулю, округление к нулю (англ. fix) — это самое «простое» компьютерное округление, заключающееся в «отбрасывании» «лишних» цифр. (11.9 становится равным 11, −0.9 становится равным 0, −1.1 становится равным −1). Иногда округление к нулю ещё называют англ. truncate, потому что для выполнения подобного округления достаточно при выводе числа обрезать поле вывода по нужному количеству знаков.
- • случайное округление — если N+1 знак равен 5, то число округляется в меньшую или большую сторону в случайном порядке.
- • чередующееся округление — каждый раз, когда N+1 знак равен 5, то число поочерёдно округляется в большую и меньшую сторону.
- • ненулевое округление — округление производится согласно правилам математического округления, однако если округляется ненулевое число, результатом округления которого должен стать 0, округление производится «от нуля».
+8
про мантису спорить не буду. верю. знаю что это так.
просто функция round в разных языках работает по разному, и статистическое поведение встречается достаточно часто. взять хотябы тотже .net
просто функция round в разных языках работает по разному, и статистическое поведение встречается достаточно часто. взять хотябы тотже .net
0
Ну что же вы хотели от чисел с плавающей точкой.
бубен из математики:
1 = 9/9 = 9 * ( 1 / 9 ) = 9 * 0.111(1) = 0.999(9)
бубен из математики:
1 = 9/9 = 9 * ( 1 / 9 ) = 9 * 0.111(1) = 0.999(9)
+6
А вроде ещё в школе должны говорить что девятки в периоде не существует :)
-9
Почему не существует?
Просто 0,(9) тождественно равно единице (можете убедиться, просуммировав геометрическую прогрессию)
Просто 0,(9) тождественно равно единице (можете убедиться, просуммировав геометрическую прогрессию)
+6
Врёте вы все:)) Мне такого не в физмат школе, не на мат факе не говорили.
-3
На ВМК этого почему-то не говорили :'(
-4
— Хорошо, — сказал я. — Я тоже задам последовательность вопросов о
местоположении.
— Задавай, задавай, — пробормотал Чапаев.
— Начнем по порядку. Вот вы расчесываете лошадь. А где находится эта
лошадь?
Чапаев посмотрел на меня с изумлением.
— Ты что, Петька, совсем охренел?
— Прошу прощения?
— Вот она.
местоположении.
— Задавай, задавай, — пробормотал Чапаев.
— Начнем по порядку. Вот вы расчесываете лошадь. А где находится эта
лошадь?
Чапаев посмотрел на меня с изумлением.
— Ты что, Петька, совсем охренел?
— Прошу прощения?
— Вот она.
+1
Из курса математики числа не равны в том случае, если между ними есть другое число, в данном случае числа равны.
0
как так?
ну вот возьми два множества: (-∞,1) и [1, +∞). эти множества не пересекаются, как могут быть равны 0.(9) и 1, если они принадлежат разным непересекающимся множествам?
ну вот возьми два множества: (-∞,1) и [1, +∞). эти множества не пересекаются, как могут быть равны 0.(9) и 1, если они принадлежат разным непересекающимся множествам?
0
Тут вы не правы.
Они равны, поэтому будут оба во втором множестве.
Они равны, поэтому будут оба во втором множестве.
0
Множества? Окей.
Разделим второе множество на два: [1, 5] и всё остальное (1). Множество [1, 5] — замкнутое (любая точка из множества A=R\[1,5] принадлежит A вместе с некоторой окрестностью). Множество является замкнутым тогда и только тогда, когда оно содержит все свои предельные точки (отсылаю к доказательству соответствующего критерия). В любой окрестности предельной точки множества содержится бесконечное множество точек этого множества (по определению предельной точки).
Выберем некоторую окрестность E точки 0.(9). Пусть радиус этой окрестности r=0.0… k...01 (k нулей после запятой). 0.(9) + r = 1.0… k...00(9). Таким образом, в выбранной окрестности E лежит бесконечное множество [1, 1.0… k...00(9)) точек из [1, 5]. Из произвольности выбора E следует то же заключение для любой окрестности. Следовательно, 0.(9) — предельная точка множества [1, 5]. Так как [1, 5] замкнуто, то оно содержит все свои предельные точки, то есть и 0.(9). Из разбиения (1) следует, что 0.(9) принадлежит множеству [1, +inf).
Угу?
Разделим второе множество на два: [1, 5] и всё остальное (1). Множество [1, 5] — замкнутое (любая точка из множества A=R\[1,5] принадлежит A вместе с некоторой окрестностью). Множество является замкнутым тогда и только тогда, когда оно содержит все свои предельные точки (отсылаю к доказательству соответствующего критерия). В любой окрестности предельной точки множества содержится бесконечное множество точек этого множества (по определению предельной точки).
Выберем некоторую окрестность E точки 0.(9). Пусть радиус этой окрестности r=0.0… k...01 (k нулей после запятой). 0.(9) + r = 1.0… k...00(9). Таким образом, в выбранной окрестности E лежит бесконечное множество [1, 1.0… k...00(9)) точек из [1, 5]. Из произвольности выбора E следует то же заключение для любой окрестности. Следовательно, 0.(9) — предельная точка множества [1, 5]. Так как [1, 5] замкнуто, то оно содержит все свои предельные точки, то есть и 0.(9). Из разбиения (1) следует, что 0.(9) принадлежит множеству [1, +inf).
Угу?
0
ыхыхы, сталкивался 2 года назад с подобным
<? php
$L = 131.17;
$a = ($L*100);
echo $a.«
»;
$a=intval($a);
echo $a.«
»;
?>
первое echo выдаст нам 13117
а второе 13116
также интересно что при $L=131.16 все будет корректно и при $L=131.18.
<? php
$L = 131.17;
$a = ($L*100);
echo $a.«
»;
$a=intval($a);
echo $a.«
»;
?>
первое echo выдаст нам 13117
а второе 13116
также интересно что при $L=131.16 все будет корректно и при $L=131.18.
0
помоему в ф-ии round() надо выставлять до какого именно числа после запятой округлять. round($value,1)
0
$value = 97.5;
var_dump($value, round($value,1)); // float(97.5) float(97.5)
$value = (9.975-9)*100;
var_dump($value, round($value,1)); // float(97.5) float(97.5)
var_dump($value, round($value,1)); // float(97.5) float(97.5)
$value = (9.975-9)*100;
var_dump($value, round($value,1)); // float(97.5) float(97.5)
0
2+2=4
ахахахаха
ахахахаха
-14
вы вообще знаете, как компьютер работает? я не говорю про вентили-шментили, а хотя бы как работа с числами примерно происходит?
+3
web-разработчик — программист лишь с большой натяжкой
+2
зависит от того, как туда попасть. тоже самое скоро можно будет сказать, например, про нэт.
но суть-то не в этом. неужели нельзя хотя бы ради интереса изучить этот вопрос?
но суть-то не в этом. неужели нельзя хотя бы ради интереса изучить этот вопрос?
+5
я думаю, что программистов, можно разделить на три типа: те, которые начали изучение программирования с веба, на тех, которых через него «прошли» и тех, кто остановился на «вебе».
если программист желает развиться (даже в веб-программировании), то ему все-равно придется уходить из этой области в другие.
веб и, php в частности, слишком абстрактны, что бы требовать от программиста знание о экспоненциальной записи числа. а те, кому такие моменты интересны, рано или поздно займутся настоящим программированием.
если программист желает развиться (даже в веб-программировании), то ему все-равно придется уходить из этой области в другие.
веб и, php в частности, слишком абстрактны, что бы требовать от программиста знание о экспоненциальной записи числа. а те, кому такие моменты интересны, рано или поздно займутся настоящим программированием.
+3
0_o А веб-программирование разве не настоящее?
+1
Как известно программисты бывают 10 типов: те, кто знает двоичное исчисление и те, кто не знает ©
Пока программирование делится на «веб-» и «не веб-», существуют те самые говнокодеры. Сам верстак и JS-кодер, но про представление чисел с плавающей точкой в курсе со школы ещё с паскаля. Очень печально, что сейчас учатся программировать на PHP, а не программировать…
Пока программирование делится на «веб-» и «не веб-», существуют те самые говнокодеры. Сам верстак и JS-кодер, но про представление чисел с плавающей точкой в курсе со школы ещё с паскаля. Очень печально, что сейчас учатся программировать на PHP, а не программировать…
0
Как известно программисты бывают 10 типов: те, кто знает двоичное исчисление и те, кто не знает ©
Если программист не знает двоичного исчисления — то меня терзают смутные сомнения в способностях такого программиста.
Тут нужно употреблять не программисты, а люди.
0
Сейчас не все кто пишет — учатся.
0
Обижаете. Я раньше работал в институте кибернетики разрабатывал систему распознавания образов. А сейчас сайты делаю.
+3
Не важно, как он работает. Проблема в том, что он работает неправильно.
-1
Не соглашусь. Я считаю, что понимать, как оно там работает — самое важное. Потому что иначе ничего не остается, кроме как констатировать наличие проблемы.
А с сабжем вы встретитесь в любом яп'е.
А с сабжем вы встретитесь в любом яп'е.
+1
Совершенно точно подмечено :)
Когда у нас во время разработки случается не предвиденный результат, мы друг другу говорим:
«Ты, же знаешь! PHP не врет» :)
Т.е. сам где-то накосячил, или не понимаешь как это должно рабоать.
Когда у нас во время разработки случается не предвиденный результат, мы друг другу говорим:
«Ты, же знаешь! PHP не врет» :)
Т.е. сам где-то накосячил, или не понимаешь как это должно рабоать.
0
PHP врет. И я лично с этим встречался. И это называется «баги». Кроме того, habrahabr.ru/blogs/humour/40681/#comment_990975
0
Я не вижу ничего хорошего в том, что с сабжем я встречусь в любом яп'е. И ваше утверждение, если хорошо подумать, неразумно. Если как оно там работает — самое важное, то следуя Вашей логике, необходимо разобраться как работает процессор, выучить ассемблер и отрастить длинную-длинную бороду как у Кернигана и Ритчи. Звучит конечно очень красиво, но это глупость. PHP-программист должен писать web-приложения, а разработчик ЯП — устранять подобные ошибки с мантиссой. И будет именно так, потому что ЭТО разумно, а round(round($value,1)) — нет.
0
Я поясню свою мысль.
Нужно знать язык, на котором пишешь.
Данный топик — рассмотрен в PHP manual.
И это не баг мантиссы, а следствие работы с неточным типом.
А баги самого PHP встречаются гораздо реже, чем те же опечатки.
Нужно знать язык, на котором пишешь.
Данный топик — рассмотрен в PHP manual.
И это не баг мантиссы, а следствие работы с неточным типом.
А баги самого PHP встречаются гораздо реже, чем те же опечатки.
+1
Ну да. Ещё разработчик ЯП должен устранять проблемы со сложностью алгоритмов, объёмом оперативной памяти, ОО проектированием и всем прочим, что PHP-программист не захотел выучить.
Вы готовы простить интерпретатор вообще за наличие округления? А то оно же в принципе не нужно. Ограниченность ресурсов ЭВМ — это низкоуровневые детали реализации, они не должны касаться PHP-программиста!
На досуге попытайтесь изобрести своё представление двоичного числа с плавающей точкой, в котором этой «ошибки» не будет. Это интересно, Вас ждёт ряд сюрпризов.
Вы готовы простить интерпретатор вообще за наличие округления? А то оно же в принципе не нужно. Ограниченность ресурсов ЭВМ — это низкоуровневые детали реализации, они не должны касаться PHP-программиста!
На досуге попытайтесь изобрести своё представление двоичного числа с плавающей точкой, в котором этой «ошибки» не будет. Это интересно, Вас ждёт ряд сюрпризов.
0
Если существует нечто под названием «BC Math», то это уже — способ представления двоичного числа с плавающей точкой, в котором этой «ошибки» не будет. Более того, сама строка «0.1» или «(9.975-9)*100» — это тоже еще один способ представления числа, лишенный погрешности, в котором искомое число записывается в виде последовательности двоичных чисел.
К счастью, изобретать свое представление двоичного числа с плавающей точкой я не буду, потому что складирование мёртвых нигеров — это не мой бизнес. Пусть лучше этим займутся разработчики ЯП — у них должно получиться в сто раз более качественное решение, чем то, до которого могу додуматься я, если только они не будут делать как Вы, утверждая что математическое выражение (97.5 != (9.975-9)*100) это даже и не ошибка.
К счастью, изобретать свое представление двоичного числа с плавающей точкой я не буду, потому что складирование мёртвых нигеров — это не мой бизнес. Пусть лучше этим займутся разработчики ЯП — у них должно получиться в сто раз более качественное решение, чем то, до которого могу додуматься я, если только они не будут делать как Вы, утверждая что математическое выражение (97.5 != (9.975-9)*100) это даже и не ошибка.
0
Постарайтесь — как профессиональный разработчик на PHP — на досуге понять, почему представление чисел с плавающей точкой, допускающее погрешность, повсеместно используется. Вам будет интересно узнать, насколько SSE-инструкции Вашего процессора быстрее, чем это:
Полюбуйтесь на свой BC Math. Если бы числа с плавающей точкой всегда представлялись в таком виде, мы бы до сих пор сидели в каменном веке.
Изучите вопрос, прежде чем спорить.
typedef enum {PLUS, MINUS} sign; typedef struct bc_struct *bc_num; typedef struct bc_struct { sign n_sign; int n_len; /* The number of digits before the decimal point. */ int n_scale; /* The number of digits after the decimal point. */ int n_refs; /* The number of pointers to this number. */ bc_num n_next; /* Linked list for available list. */ char *n_ptr; /* The pointer to the actual storage. If NULL, n_value points to the inside of another number (bc_multiply...) and should not be "freed." */ char *n_value; /* The number. Not zero char terminated. May not point to the same place as n_ptr as in the case of leading zeros generated. */ } bc_struct;
Полюбуйтесь на свой BC Math. Если бы числа с плавающей точкой всегда представлялись в таком виде, мы бы до сих пор сидели в каменном веке.
Изучите вопрос, прежде чем спорить.
0
Вы, кстати, сами чудесно демонстрируете, зачем начинающие программисты учат ассемблер.
Развитие вычислительной техники представляет собой непрерывную цепочку компромиссов — между производительностью и занимаемой памятью, между производительностью и точностью, между производительностью и ценой… Для того, чтобы обсуждать принятое однажды решение (например, пресловутый стандарт IEEE 754), нужно знать альтернативы этому решению, их достоинства и недостатки. Для этого и следует понимать основы архитектуры ЭВМ.
Вы хотите всё и сразу, но так не бывает. «Высокоуровневый» язык программирования прячет от Вас ряд деталей реализации, но нельзя рассчитывать, что он будет прятать их все и всегда. И, когда сквозь дырку в абстракции языка начинают лезть ошибки округления, проблемы с кодировкой и т. п., Вы должны знать, что происходит.
Ещё рекомендую прочесть local.joelonsoftware.com/mediawiki/index.php/Закон_Дырявых_Абстракций — Джоэл умнее меня, и язык у него подвешен лучше.
Развитие вычислительной техники представляет собой непрерывную цепочку компромиссов — между производительностью и занимаемой памятью, между производительностью и точностью, между производительностью и ценой… Для того, чтобы обсуждать принятое однажды решение (например, пресловутый стандарт IEEE 754), нужно знать альтернативы этому решению, их достоинства и недостатки. Для этого и следует понимать основы архитектуры ЭВМ.
Вы хотите всё и сразу, но так не бывает. «Высокоуровневый» язык программирования прячет от Вас ряд деталей реализации, но нельзя рассчитывать, что он будет прятать их все и всегда. И, когда сквозь дырку в абстракции языка начинают лезть ошибки округления, проблемы с кодировкой и т. п., Вы должны знать, что происходит.
Ещё рекомендую прочесть local.joelonsoftware.com/mediawiki/index.php/Закон_Дырявых_Абстракций — Джоэл умнее меня, и язык у него подвешен лучше.
0
Сравнение чисел с плавающей запятой напрямую (а не их скажем разости) — моветон.
+7
И источник ошибок (даже не потенциальный, а самый что ни на есть реальный).
0
C разностью тоже надо быть осторожным, я выше приводил пример:
Ошибка появляется очень быстро:
0.1 + 0.1 + 0.1 - 0.3 = 5.6e-17 != 0
Ошибка появляется очень быстро:
0.1 + 0.1 - 0.1 = 0.10000000000000001
0
Имеется ввиду сравнение этих чисел через разность, с учётом погрешности:
e = 0.000001 a = 0.1 + 0.1 + 0.1 - 0.3 if( abs( a ) < e ) ... a = 0.1 + 0.1 - 0.1 b = 0.1 if( abs(a - b) < e ) ...
+1
C разностью тоже надо быть осторожным, я выше приводил пример:
0.1 + 0.1 + 0.1 — 0.3 = 5.6e-17 != 0
Вы опять напрямую сравниваете (!=)
0
To everybody above:
Не, я согласен и знаю что флоат сравнивать плохо и т.п.
Просто почему-то был уверен что var_dump всегда показывает непременно точное значение :-/ Весь мой дебагинг, можно сказать, строится на этом как на трех китах, и тут такой облом. Простите за «юмор», это нервное — когнитивный диссонанс-с :)
Не, я согласен и знаю что флоат сравнивать плохо и т.п.
Просто почему-то был уверен что var_dump всегда показывает непременно точное значение :-/ Весь мой дебагинг, можно сказать, строится на этом как на трех китах, и тут такой облом. Простите за «юмор», это нервное — когнитивный диссонанс-с :)
0
Надо же, ещё один человек узнал об этом. Ещё чуть-чуть и вы догадаетесь, вероятно, почитать о представлении чисел в языках программирования. Откроете для себя новый мир: узнаете с чем связан этот эффект, для чего нужен тип decimal в СУБД и JS2 и так далее. Завидую вам.
Для справки:
python -c 'print round((9.975-9)*100)'
97.0
Читайте руководство по языку, там многое описано. В том числе и то, с чем вы столкнулись.
Для справки:
python -c 'print round((9.975-9)*100)'
97.0
Читайте руководство по языку, там многое описано. В том числе и то, с чем вы столкнулись.
+5
Если кто читает PHP Internal Mailing list то там эту тему подняли, предложили патч и помоему его добавят в PHP 5.3. В следствии этого точность вычислений должна возрасти.
0
Собственно вот линкб помечено как Active: wiki.php.net/rfc/rounding
+1
Что, числа будут храниться не в формате IEEE 754?
0
НЛО прилетело и опубликовало эту надпись здесь
PHP тут не при чем. Так работает процессор с числами с плавающей точкой.
+1
denver & Co. читайте bugs.php.net и PHP Internal Mailing list и будет вам счастье
0
Кстати есть интересная статья на эту тему www.delphikingdom.com/asp/viewitem.asp? catalogID=1217
0
О, сколько нам открытий чудных… [C] Как говорили древние: RTFM.
0
Извечная проблема потери точности при работе с числами с плавающей точкой :)
Практически в любом языке.
Выход, где это _возможно_, использовать целочисленную арифметику.
Всегда можно представить 9.975 как 9975, а 97.5 как 97500 :)
Практически в любом языке.
Выход, где это _возможно_, использовать целочисленную арифметику.
Всегда можно представить 9.975 как 9975, а 97.5 как 97500 :)
0
а ceiling и floor для кого?
-1
или обязательно нужен float? не очень ясно из поста, комментарии информативнее :)
-1
Нужно было именно округление, а то бы конечно юзал ceil или floor.
0
Вот, примерно, как мы делали лет 5-7 назад в Pascal :)
function round2($a) { return round($a + 1e-8); } $value = 97.5; var_dump($value, round2($value)); // float(97.5) float(98) $value = (9.975-9)*100; var_dump($value, round2($value)); // float(97.5) float(98)
0
А как вы определили константу 1e-8?
Попутно замечу:
Попутно замечу:
round(0.49999999999) = 0
round2(0.49999999999) = 1
0
Не совсем уверен что топик стоило выносить на индекс, но раз вывели, то топик стоило логически завершить хотя бы заглянув на офф сайт php
ru.php.net/float
Тогда многих комментариев вроде
Просто бы не появилось и все остались бы со своими плюсами, а пользователи прочитавшие пост узнали что в php может случится и такой казус.
ru.php.net/float
Тогда многих комментариев вроде
смею предположить, что в PHP реализовано статистическое округление
Просто бы не появилось и все остались бы со своими плюсами, а пользователи прочитавшие пост узнали что в php может случится и такой казус.
0
Знаете, что такое «коротко и лаконично»? 2 х 2 = 5. И это, кстати, доказуемо.
-2
Материалы по предмету «Программирование вычислений».
Касательно вопроса топика — Представление чисел в ЭВМ или В.И. Юров — Assembler (стр. 510-519). Последний вариант весит меньше, но при этом — интересная книга целиком :) Ну и википедия.
Так же вопрос освещён в местных материалах по ПВ, но где именно — уже не помню.
Касательно вопроса топика — Представление чисел в ЭВМ или В.И. Юров — Assembler (стр. 510-519). Последний вариант весит меньше, но при этом — интересная книга целиком :) Ну и википедия.
Так же вопрос освещён в местных материалах по ПВ, но где именно — уже не помню.
0
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
Зарегистрируйтесь на Хабре , чтобы оставить комментарий
Бубен в PHP