LINUX.ORG.RU

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

ziemin ★★
()

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

amomymous ★★★
()
Ответ на: комментарий от 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
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.