【问题标题】:Using Perl to split a float使用 Perl 拆分浮点数
【发布时间】:2015-03-06 03:31:22
【问题描述】:

为什么我使用 split 会丢失精度? 我的目标是只得到小数部分,全部。

$a = 123456789.123456789;
@b = split(/\./, $a);
$baseDec = "." . $b[1];

上面给出 $baseDec == .123457

但这给出了正确的精度: 这是正确的方法吗? 更正:这给出了同样糟糕的精度! 我没有正确测试代码。对不起!

$a = 123456789.123456789;
@b = split(/\./, $a);
$baseInt = $b[0];
$baseDec = $a - $baseInt;

我应该使用 Math::BigFloat 吗?

编辑: $a 应该是一个字符串$a = "123456789.123456789";,然后原始代码就可以工作了。在我弄清楚如何让我的 Perl 与 longdouble 一起工作之前,我无法测试原始问题。答案似乎是我失去了精度,因为 $a 被存储在一个双精度位(52 位 ~ 15 个十进制数字,如下面的@Ben 所述)。 print $a 给了123456789.123457

【问题讨论】:

    标签: perl split floating-point precision


    【解决方案1】:

    你可以使用int:

     $a = 123456789.123456789;
     $baseDec = $a - int($a);
    

    【讨论】:

    • 你实际测试过这个吗?当我尝试printf("%.9f", $baseDec); 时,结果为0.123456791,而不是0.123456789
    【解决方案2】:

    您丢失了精度,因为 123456789.123456789 是一个数字文字,默认情况下,Perl 编译器将其存储在 double(52 位,约 15 个十进制数字)$a 中。接下来,当@b = split(/\./, $a); 运行时,$a 被隐式强制转换为字符串,然后才能成为split

    如果您的 Perl 编译为使用 longdoubles(请参阅:perl -V:uselongdoubleperl -V:doublesize),则数字文字将用 80 位(约 21 个十进制数字)和字符串强制表示。

    【讨论】:

    • perl -V 在 Linux 上给了我和你一样的东西。在 Sun4-Solaris 上,它是(颠倒的字节顺序 -- 不是问题):intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=87654321d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16
    • 您的原始代码能否在 Solaris 上正常工作?
    • 不,我的代码没有按说明工作。我犯了在没有适当测试的情况下写问题的错误! $a 应该是一个字符串,然后代码就可以工作了。我认为 longdouble 没有被使用。 print $a123456789.123457。感谢@Ben 抽出时间来解开一个欺骗性的问题!
    【解决方案3】:

    如果您要将其视为字符串,请一直这样做。你不会在没有引号的情况下分配一个字符串,对吧?

    my $a = "123456789.123456789";
    

    【讨论】:

    • 是的,你看穿了我不小心的欺骗性问题! $a 实际上是我代码中的一个字符串,如果我保持这种方式,它就可以正常工作。
    【解决方案4】:

    你可以使用 sprintf 获取它:

    my $a = 123456789.123456789;
    my @b = split(/\./, sprintf("%.8f",$a));
    my $baseDec = "." . $b[1];
    print $baseDec;
    

    【讨论】:

    • 你不是说"%.9f"吗?
    • 即使这样结果也不正确(.123456791,不是.123456789)。 printf("%.15f", $a) 结果为 123456789.123456791043282
    猜你喜欢
    • 1970-01-01
    • 2016-07-20
    • 1970-01-01
    • 1970-01-01
    • 2015-09-09
    • 2014-06-21
    • 1970-01-01
    • 2014-12-27
    • 1970-01-01
    相关资源
    最近更新 更多