2009-10-30 2 views
5

Меня не интересовало соглашение об округлении, используемое встроенной функцией Perl sprintf.Почему спринт Perl не округляет числа с плавающей запятой правильно?

Я думал, что это делает обычный округление (например, ROUND_HALF_UP как в Java's rounding mode convention), но рыть дальше оказалось, что это не так:

> /usr/local/bin/perl5.10.1 -e 'print(sprintf("%.2f", shift @ARGV)."\n");' 0.335 
0.34 
> /usr/local/bin/perl5.10.1 -e 'print(sprintf("%.2f", shift @ARGV)."\n");' 1.335 
1.33 
+7

печать (sprintf (...))? Интересно, есть ли «printf» ... – jrockway

+1

Взгляните на [Perl Cookbook recipe 2.2 - округление чисел с плавающей запятой] (http://books.google.com/books?id=hP4IRp8xwTkC&pg=PA64&lpg=PA64&dq= округления + номер + Perl + поваренная книга и источник = бли & отс = ti7Tyxr3s7 & сиг = gyWX-iySyiVZef0vB43ZuIaxkuw & гл = еп & е = RPzrStmzO4z0MarIvKkI & са = Х & OI = book_result & кт = результат & resnum = 1 & веды = 0CAwQ6AEwAA # v = OnePage & д = & F = ложь) для более полного объяснения – heferav

ответ

16

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

DB<1> $a=0.335 

    DB<5> print sprintf("%.19f",$a) 
0.3350000000000000200 
    DB<7> $b=1.335 

    DB<8> print sprintf("%.19f",$b) 
1.3349999999999999645 
    DB<9> 

Поскольку 0,335 представлена ​​внутренне как немного больше, чем 0,335 она округляется до .34, в то время как 1,335 немного меньше, чем 1,335, так что она округляет до 1,33.

6

Это функция чисел с плавающей запятой IEEE.

Для получения дополнительной информации в контексте Perl см. Perlfaq4 "Does Perl have a round() function" и, в частности, то, что он говорит о чередовании с половинной точкой.

Смежные вопросы