LINUX.ORG.RU

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

ziemin ★★
()

Ты очень удивишься еще, но в этом ужасном php (1.0/3.0)*3.0 совсем не равно 1! А еще, оказывается, такая проблема и во многих других языках встречается, вот чудесные компьютеры-то, не могут простейшую формулу без ошибок вычислить.

amomymous ★★★
()
Ответ на: комментарий от amomymous

Дак а почему? Кинь ссылку, почитаю. Мне интересно, правда.

emissar ★★
() автор топика
Последнее исправление: emissar (всего исправлений: 1)
Ответ на: комментарий от emissar

http://www.techradar.com/news/computing/why-computers-suck-at-maths-644771/1 достаточно для блондинок?

TL;DR: floating point-вычисления неточны из-за перевода между двоичной и десятичной СС. Не сравнивай floating point-числа через == либо юзай fixed-point.

x3al ★★★★★
()
Ответ на: комментарий от emissar

Это не только не баг. Это еще и не баг не только в PHP. Блин, этому баяну лет 20 только в моей личной истории. Это ты такое выкопал?

Suntechnic ★★★★★
()
Ответ на: комментарий от x3al

Я бы дополнил: при выводе floating-point числа нужно округлять (или применять формат). Ну и помнить всегда про возможность накопления ошибки.

amomymous ★★★
()
Ответ на: комментарий от amomymous

Я бы дополнил: при выводе floating-point числа нужно округлять

Вот классический Бейсик почти всегда имел при вычислении 1-2 лишних цифры точности по сравнению с отображаемыми/проверяемыми. Как следствие «ошибка» вылезала внезапно, по мере накопления погрешности в циклических вычислениях. Но об этом в любой книжке по программированию писали. Зато простой PRINT всегда числа красивые писал. Когда впервые с Си познакомился, вывод чисел с полной точностью с одной стороны прикалывал (офгеть! 14 цифр разрядности там, где у Бейсика было 12), с другой — раздражала некрасивость чисел и необходимость использовать форматирование при печати :)

KRoN73 ★★★★★
()

А ты знаешь, что с точки зрения математики 0.(9) равно 1?
Причём равно строго?
Вот только в PHP нет понятия периода.
Так что если тебе эти числа нужны для рассчётов, а не для того, чтобы школьников озадачивать, то всё будет хорошо.

Stahl ★★☆
()
Ответ на: комментарий от Suntechnic

этому баяну лет 20 только в моей личной истории. Это ты такое выкопал?

если человек пхпэшник, то это подразумевает, что он зачастую слабо понимает о всяких внутренностях.

fornlr ★★★★★
()
CL-USER> (loop :for i :downfrom 30 :to 29.9 :by 0.01
	      :do (print i))

30 
29.99 
29.98 
29.97 
29.96 
29.949999 
29.939999 
29.929998 
29.919998 
29.909998 
NIL
CL-USER> 

Это потому, что компьютер всё это считает и округляет в двоичном виде. Есть алгоритмы с софтварными операциями над десятичными числами, но они очень медленные.

ados ★★★★★
()
Последнее исправление: ados (всего исправлений: 1)
Ответ на: комментарий от ados

> Есть алгоритмы с софтварными операциями над десятичными числами, но они очень медленные.

та лан сказки тут нам травить ))

$ time php -r 'for($i=30;$i>0;$i-=0.01)echo $i.", ";'

real 0m0.120s user 0m0.020s sys 0m0.008s

test.tcl:

set tcl_precision 12
for { set i  30} { $i > 0} { set i [expr $i - 0.01]} {puts $i };

$time tclsh8.4 test1.tcl ... 0.2 0.19 0.18 0.17 0.16 0.15 0.14 0.13 0.12 0.11 0.1 0.09 0.08 0.07 0.06 0.05 0.04 0.03 0.02 0.01

real 0m0.079s user 0m0.052s sys 0m0.012s

$time tclsh8.5 test1.tcl

...

0.19 0.18 0.17 0.16 0.15 0.14 0.13 0.12 0.11 0.1 0.09 0.08 0.07 0.06 0.05 0.04 0.03 0.02 0.01

real 0m0.082s user 0m0.040s sys 0m0.020s

bedcasus ★
()

Это связано с двоичным представлением чисел, во многих языках так.

TDrive ★★★★★
()
Ответ на: комментарий от emissar

Дак а почему?

Даю наводку - переведи число 0.01 в двоичную систему счисления.

no-such-file ★★★★★
()
Ответ на: комментарий от bedcasus

та лан сказки тут нам травить ))

0m0.020s
0m0.040s

Даже с этим «измерением стартапа» и то вдвое.

А если так:

<?php

$sum=0;

for($i=1; $i <= 1000000; $i++)
    $sum += $i;

echo $sum;

set tcl_precision 12;
set sum 0;
for {set i  1} { $i <= 1000000} { set i [expr $i + 1]} {set sum [expr $sum + $i]};
puts $sum;
$ time php sum.php
500000500000
real    0m0.142s
user    0m0.124s
sys     0m0.012s

$ time tclsh8.4 sum.tcl
1784293664

real    0m7.225s
user    0m7.124s
sys     0m0.012s

57 раз разницы, да ещё и результат неверный :) (я так понимаю, что переполнение 32-х битного результата?)

KRoN73 ★★★★★
()

рнр-шники открывают для себя принципы работы компьютера.

Deleted
()

сначала получи нормальный результат останова на php

Переведи на русский.

1000001

Результат неверный. Задача Гаусса же.

sum = (n+1)*n/2


В наше время такое в школе учили.

:)

KRoN73 ★★★★★
()
Последнее исправление: KRoN73 (всего исправлений: 1)
Ответ на: комментарий от bedcasus

та лан сказки тут нам травить

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

ados ★★★★★
()
Ответ на: комментарий от KRoN73

ошибки и неточность там ...
правильно будет как-то так:

for { set i 1; set sum 0 } { $i <= 1000000} {incr i} {set sum [expr $sum + $i]}

puts $sum ;

и запускать под tcl 8.5

но ....
и тут интересные штуки и тут получаются ))
$ time tclsh8.5 test2.tcl
5050
для i <= 100

real 0m0.010s
user 0m0.004s
sys 0m0.000s


$ time php test2.php
5050
real 0m0.016s
user 0m0.012s
sys 0m0.004s
----------------------------------------------
для i <= 1000

$ time tclsh8.5 test2.tcl
500500

real 0m0.016s
user 0m0.012s
sys 0m0.004s

$ time php test2.php
500500
real 0m0.017s
user 0m0.008s
sys 0m0.008s
----------------------------------------------
для i <= 10000

$ time tclsh8.5 test2.tcl
50005000

real 0m0.120s
user 0m0.104s
sys 0m0.000s

$ time php test2.php
50005000
real 0m0.021s
user 0m0.012s
sys 0m0.004s
----------------------------------------------
для i <= 100000

$ time tclsh8.5 test2.tcl
5000050000

real 0m1.046s
user 0m1.036s
sys 0m0.000s

$ time php test2.php
5000050000
real 0m0.029s
user 0m0.024s
sys 0m0.008s
----------------------------------------------
для i <= 1000000

$ time tclsh8.5 test2.tcl
500000500000

real 0m16.703s
user 0m16.521s
sys 0m0.004s

$ time php test2.php
500000500000
real 0m0.354s
user 0m0.304s
sys 0m0.012s

bedcasus ★
()
Ответ на: комментарий от x3al

Не сравнивай floating point-числа через == либо юзай fixed-point.

У него проблема вовсе не в сравнении. Ему непонятно, почему строковое представление чисел получается таким.

theNamelessOne ★★★★★
()
Ответ на: комментарий от ziemin

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

qnikst ★★★★★
()

вброса говнеца на вентилятор у автора не получилось

umren ★★★★★
()
Последнее исправление: umren (всего исправлений: 1)

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

Vit ★★★★★
()

Почему так?

Попробуй перевести на бумаге десятичную дробь в двоичную систему и обратно.

Похоже информатику в школе уже перестали преподавать.

sergej ★★★★★
()

... 0.03999999999811, 0.02999999999811, 0.01999999999811, 0.0099999999981099,

# php -v
PHP 5.5.5-1 (cli) (built: Oct 19 2013 22:09:48)

Ford_Focus ★★★★★
()

man числа с плавающей точкой. Они в любом ЯП представляются в таком виде.

vurdalak ★★★★★
()
Ответ на: комментарий от x3al

неточны из-за перевода между двоичной и десятичной СС.

Нет.

Из-за того, что любая СС неточна. Что 0.1 в двоичной, что 1/3 в десятичной.

anonymous
()
Вы не можете добавлять комментарии в эту тему: топик перемещен в архив.