为什么Perl的sprintf不能正确舍入浮点数?

Jag*_*aga 5 floating-point perl printf

我一直在寻找Perl内置函数sprintf使用的舍入约定.

我认为它进行了正常的舍入(例如在Java的舍入模式约定中的 ROUND_HALF_UP ),但挖掘进一步证明这是错误的:

> /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
Run Code Online (Sandbox Code Playgroud)

Jim*_*son 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> 
Run Code Online (Sandbox Code Playgroud)

由于0.335在内部表示为略大于0.335,因此其舍入为.34,而1.335略低于1.335,因此其舍入为1.33.


jmc*_*ara 6

这是IEEE浮点数的函数.

有关更多信息,请参阅Perl上下文,请参阅Perlfaq4"Perl是否具有round()函数",特别是关于中间点交替的内容.