Perl舍入错误再次出现

栏目: Perl · 发布时间: 5年前

内容简介:翻译自:https://stackoverflow.com/questions/24493228/perl-rounding-error-again

显示问题的示例:

>有一个数字105;

>除以1000(结果0.105)

>粗略到2位小数应为:0.11

现在,几个脚本 – 基于另一个问题的答案:

这大多是推荐的,并且大多数是使用printf的upvoted解决方案.

use 5.014;
use warnings;
my $i = 105;
printf "%.2f\n", $i/1000;   #prints 0.10

但打印错误的结果.在评论中

https://stackoverflow.com/a/1838885 @Sinan Unur说(6次评论):

Use sprintf(“%.3f”, $value) for mathematical purposes too.

但是,它“有时”不起作用……就像上面一样.

另一个推荐的解决方案Math :: BigFloat:

use 5.014;
use warnings;
use Math::BigFloat;
my $i = 105;

Math::BigFloat->precision(-2);
my $r = Math::BigFloat->new($i/1000);

say "$r";   #0.10 ;(

错误的结果也是如此.另一个推荐了一个bignum:

use 5.014;
use warnings;
use bignum ( p => -2 );
my $i = 105;
my $r = $i/1000;
say "$r";   #0.10 ;(

又错了. (

现在工作的人:

use 5.014;
use warnings;
use Math::Round;
my $i = 105;
say nearest(0.01, $i/1000); #GREAT prints 0.11 :)

好结果0.11,但是在这里发表评论 https://stackoverflow.com/a/571740

抱怨它.

最后另一个推荐“我自己的”功能:

use 5.014;
use warnings;
my $i = 105;
my $f = $i/1000;

say myround($f,2);  # 0.11

sub myround {
    my($float, $prec) = @_;
    my $f = $float * (10**$prec);
    my $r = int($f + $f/abs($f*2));
    return $r/(10**$prec);
}

也打印0.11,但无法证明它的正确性.

作为参考,我读到:

> How do you round a floating point number in Perl?

> In Perl, how can I limit the number of places after the decimal point but have no trailing zeroes?

> How do I set the floating point precision in Perl?

>和许多其他人……

>最后这也是:

http://www.exploringbinary.com/inconsistent-rounding-of-printed-floating-point-numbers/

什么给这个问题提供了一个非常好的整体观点.

我明白这是所有语言的常见问题,但毕竟请

以上阅读 – 我还有这个问题:

perl 中将浮点数舍入为N的错误方法是什么?

小数位 – 用数学上正确的方式,例如会有什么结果

像105/1000正确到N个小数位没有“惊喜”……

在编程的旧整数数学时代,我们假装使用小数位:

N = 345
DISPLAY N        # Displays 345
DISPLAY (1.2) N  # Displays 3.45

在尝试正确计算销售税时,我们学到了一个有价值的技巧:

my $amount = 1.344;
my $amount_rounded = sprintf "%.2f", $amount + .005;
my $amount2 = 1.345;
my $amount_rounded2 = sprintf "%.2f", $amount2 + .005;
say "$amount_rounted   $amount_rounded2";  # prints 1.34 and 1.35

通过加上1/2的精度,我正确显示圆角.当数字为1.344时,添加.005使其成为1.349,并且切掉最后一位数字显示倾斜位于1.344.当我使用1.345执行相同的操作时,添加.005使其为1.350并删除最后一位数字将其显示为1.35.

您可以使用将返回舍入金额的子例程来执行此操作.

有趣…

这个主题有一个 PerlFAQ .它建议只使用printf来获得正确的结果:

use strict;
use warnings;
use feature qw(say);

my $number = .105;
say "$number";
printf "%.2f\n", $number;   # Prints .10 which is incorrect
printf "%.2f\n", 3.1459;    # Prins 3.15 which is correct

对于Pi,这可行,但不适用于.105.然而:

use strict;
use warnings;
use feature qw(say);

my $number = .1051;
say "$number";
printf "%.2f\n", $number;   # Prints .11 which is correct
printf "%.2f\n", 3.1459;    # Prints 3.15 which is correct

这看起来像是Perl在内部存储.105的方式的问题.可能类似于.10499999999,它可以正确向下舍入.我还注意到Perl警告我使用舍入和舍入作为可能的未来保留字.

翻译自:https://stackoverflow.com/questions/24493228/perl-rounding-error-again


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Computational Advertising

Computational Advertising

by Kushal Dave、Vasudeva Varma / Now Publishers Inc / 2014

Computational Advertising (CA), popularly known as online advertising or Web advertising, refers to finding the most relevant ads matching a particular context on the Web. The context depends on the t......一起来看看 《Computational Advertising》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具