V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
18m
V2EX  ›  问与答

Perl 数字运算的疑问

  •  
  •   18m · 2013-09-25 22:48:09 +08:00 · 3631 次点击
    这是一个创建于 4106 天前的主题,其中的信息可能已经有所发展或是发生改变。
    #! /usr/bin/perl
    $x = 4.5232 - 4.5111;
    $y = 0.5232 - 0.5111;
    print "$x\n$y\n";


    $x = 0.0121000000000002
    $y = 0.0121

    为什么会产生这样的差别? $x的0.0000000000000002 来自哪里? 我该怎么得到正确的答案?
    谢谢
    7 条回复    1970-01-01 08:00:00 +08:00
    11138
        1
    11138  
       2013-09-25 22:52:49 +08:00   ❤️ 1
    加上:
    use bignum;

    或者用 Math::BigFloat 模块解决(建议)。
    18m
        2
    18m  
    OP
       2013-09-25 22:54:24 +08:00
    非常感谢,已经解决。
    我再研究一下为什么会产生这个问题。
    polythene
        3
    polythene  
       2013-09-25 23:33:46 +08:00
    那是因为计算机本身是无法精确的表示一个浮点数的,这不是perl的问题,而是计算机本身结构的问题,你用python, ruby, c都会得到同样的结果。
    18m
        4
    18m  
    OP
       2013-09-25 23:52:06 +08:00
    @polythene
    @11138
    再谢
    假如我用 Math::BigFloat 的话应该如何做呢? cpan的说明我没看懂。我不是学计算机的,现在只是想用perl处理一堆数据,搞不明白浮点小数在计算机里面的内部机理也不想去研究太深。
    polythene
        5
    polythene  
       2013-09-26 00:20:08 +08:00
    printf("%.4f\n", 4.5232-4.5111);
    =>0.0121

    具体请谷之"perl print 浮点数"。
    11138
        6
    11138  
       2013-09-26 00:25:38 +08:00
    use Math::BigFloat;
    my $a1 = 2.25;
    my $a2 = 2.24;
    $a1 = Math::BigFloat->new($a1);
    $a2 = Math::BigFloat->new($a2);
    my $a3 = $a1 - $a2;
    print "\$a3 = $a3\n";

    另外,我不建议直接加:
    use bignum;
    是因为它与timelocal有可能出现冲突(其它的没遇过),导致结果不对。
    18m
        7
    18m  
    OP
       2013-09-26 01:23:42 +08:00
    谢谢 @polythene
    利用printf 对于我目前的数据来说精度足够了,而且性能好很多,我目前就按照这样的方法做了。
    Perl的Math::BigFloat 性能很差。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2501 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 32ms · UTC 15:34 · PVG 23:34 · LAX 07:34 · JFK 10:34
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.