• [原]再说精度用于显示的数字出现精度问题的处理(Perl/Java)


    2005年03月03日写的东西,整理了以前的博客,转到这里来。

     

     

    描述

    1. 昨天在ChinaUnix上看见一个问题:

    $ad=1.25 - 1.24;                  #$ad答案是0.01 

    #$ad答案应也是0.01,但出现的答案是0。009999999999999979...
    $ad = 2.25 - 2.24;                 

    为什麽?怎样更正? 谢


    2. 前段时间刚做完的一个TOYOTA的J2EE项目也遇到类似问题:

      把12个字段的字符串转成float再相加,每个字段都是#.##的格式,结果应该等于12.00,可实际是11.9999....,插入到Text里时还出现了越界。

    问题

    1. 精度:浮点数不能准确的表示
    2. 结果的用途:用于计算的数值出现误差时,可能导致计算结果出现很大偏差,即使不会有太大的影响最好也不要冒险;数值是用于显示时,并不一定要处理float使之符合要求,可以尝试处理字符串。本文针对后一种情况。
    3. 四舍五入:我简单的翻了一下Perl的函数库,没找到round函数。


    解决办法

      因为结果是用来显示的,所以并不一定要使float完全符合#.##的形式,可以考虑处理字符串。

      由于结果应该符合#.##的形式,也就是说就四舍五入到0.01,但round()[JAVA]和int()[Perl]只能处理整数,所以先将数值乘以100,然后转换为字符串。判断字符串长度,当长度大于1时,在length-2的位置插入“.”,否则从0位置插入“0.0”。 

    $a = 2.25 - 2.24;        # $a = 0.00999999999999979 
    $a = $a * 100 + 0.5;  # $a = 1.49999999999998 
                                      # prepare for round off 
    $a = int( $a );             # $a = 1; 

    # now, we got the int value 100 times more than the value wanted. 
    $a = "0.0" . $a           # $a = 0.01 
    # here is the value we wanted. But the value must less than 10. 
    # If we want deal with the value more than 10, we must judging
    # length of the value and whether append it "0.0" in the front 
    # or insert a "." into the string. 
    print $a;


    输出:0.01

    参考

    1.MSDN对浮点数精度的描述

    《为何浮点数可能丢失精度》

      浮点十进制值通常没有完全相同的二进制表示形式。这是 CPU 所采用的浮点数据表示形式的副作用。为此,可能会经历一些精度丢失,并且一些浮点运算可能会产生意外的结果。

    导致此行为的原因是下面之一:

      十进制数的二进制表示形式可能不精确。 
      使用的数字之间类型不匹配(例如,混合使用浮点型和双精度型)。 
      为解决此行为,大多数程序员或是确保值比需要的大或者小,或是获取并使用可以维护精度的二进制编码的十进制 (BCD) 库。

      浮点值的二进制表示形式影响浮点计算的精度和准确性。Microsoft Visual C++ 使用 IEEE 浮点格式。

    2 四舍五入的算法

      四舍五入的算法处理整数,先将数值加0.5,再取得整数部分。

      Java中的Math类有round函数,可我在Perl中没找到(可能有)。我想Perl主要是针对字符串处理,也许没有这方面的函数。所幸在Perl中找到int($)函数来截断整数。

      所以,在Perl中可以这样做:

    $value = int( $old + 0.5 );

    在Java中直接使用Math.round()。

    作者:basecn 发表于2010-6-3 22:03:00 原文链接
    阅读:124 评论:0 查看评论
  • 相关阅读:
    Linux学习之查看是否安装软件
    Linux学习之nfs实例
    Linux学习之nfs安装配置
    Linux 学习之防火墙配置
    Linux学习之系统时间同步
    Linux学习之守护进程详解
    Linux学习之Center os网络配置
    Linux学习之挂载操作
    Linux学习之挂载
    Linux学习之开机启动
  • 原文地址:https://www.cnblogs.com/basecn/p/3264317.html
Copyright © 2020-2023  润新知