Chinaunix

标题: use List::Util qw/sum/;求和结果出现很多位小数 [打印本页]

作者: jiuling    时间: 2014-01-22 13:01
标题: use List::Util qw/sum/;求和结果出现很多位小数
本帖最后由 jiuling 于 2014-01-22 13:05 编辑

use List::Util qw/sum/;
@number = (0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9);
$sum = sum @number;
print $sum;


以上是代码,94个0.9相加,打印出来的结果有很多位小数:84.6000000000001;可是当我去掉一个0.9,93个0.9相加时,打印出来的结果就很正常了:83.7。这是怎么回事?
作者: pitonas    时间: 2014-01-22 13:06
{:2_172:} 楼下
http://bbs.chinaunix.net/thread-4120063-1-1.html
作者: jiuling    时间: 2014-01-22 13:09
谢谢,可惜看不懂
作者: jiuling    时间: 2014-01-22 13:18
要怎样才能打印出不带这么多小数的结果?
作者: MMMIX    时间: 2014-01-22 14:22
jiuling 发表于 2014-01-22 13:18
要怎样才能打印出不带这么多小数的结果?


可以通过 sprintf 的 FORMAT 指定精度,详见 perldoc -f sprintf
作者: jason680    时间: 2014-01-22 14:28
回复 1# jiuling

It's no issue on ubuntu 12.04.3 LTS with Perl v5.14.2

print "$sum\n";
printf("%.1f\n", $sum);
printf("%.2f\n", $sum);

$ perl sum.pl
84.6
84.6
84.60

   
作者: q1208c    时间: 2014-01-22 14:39
这跟perl有毛关系. 这是计算系统都存在的一个问题, 就是浮点数的精度问题.

目前好象还没听说有太好的解决方案.
作者: MMMIX    时间: 2014-01-22 14:53
q1208c 发表于 2014-01-22 14:39
这跟perl有毛关系. 这是计算系统都存在的一个问题, 就是浮点数的精度问题.

目前好象还没听说有太好的解 ...


计算时把精度考虑进去(本来就应该考虑的)就是了。
作者: q1208c    时间: 2014-01-22 14:57
回复 8# MMMIX


这不是你能不能考虑的问题, 这是浮点数存储结构带来的问题.

所以, 才会有人自己实现浮点数计算的类来解决这种 加,减,乘法带来的问题, 但除法的问题, 基本上是无解的.
作者: jason680    时间: 2014-01-22 14:59
回复 7# q1208c

Math::BigFloat
http://perldoc.perl.org/Math/BigFloat.html
   
作者: jiuling    时间: 2014-01-22 15:04
回复 6# jason680


    我的是XP系统,Perl v5.16.1
作者: jiuling    时间: 2014-01-22 15:06
回复 6# jason680


   没有办法像平常计算那样加起来得出准确结果吗?
作者: jason680    时间: 2014-01-22 15:09
回复 12# jiuling

it also no issue on XP with Perl v5.14.3

C:\bat>perl -v

This is perl 5, version 14, subversion 3 (v5.14.3) built for MSWin32-x86-multi-t
hread
...


C:\bat>sum.pl
84.6
C:\bat>type sum.pl
#!/usr/bin/perl
use List::Util qw/sum/;
@number = (0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0
.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0
.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0
.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0
.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9);
$sum = sum @number;
print $sum;
C:\bat>
作者: jiuling    时间: 2014-01-22 15:13
jason680 发表于 2014-01-22 15:09
回复 12# jiuling

it also no issue on XP with Perl v5.14.3



奇怪了
作者: jiuling    时间: 2014-01-22 15:15
MMMIX 发表于 2014-01-22 14:22
可以通过 sprintf 的 FORMAT 指定精度,详见 perldoc -f sprintf


有办法打出准确结果吗?
作者: jiuling    时间: 2014-01-22 15:17
回复 13# jason680


    你再试试这个:

print 2.76-2.731;
作者: MMMIX    时间: 2014-01-22 15:28
jiuling 发表于 2014-01-22 15:15
有办法打出准确结果吗?

在精度之内结果本来就是准确的。
作者: MMMIX    时间: 2014-01-22 15:31
回复 9# q1208c


    浮点数精度有限,所以使用的时候不能当作实数,这是使用浮点数的时候必须要考虑的问题,和使用哪种浮点实现没有关系。

浮点除法并不特别复杂,也不存在什么无解的说法。
作者: jason680    时间: 2014-01-22 15:45
回复 16# jiuling


1. it's not Perl issue with float number
    all program language(ex: Java, php, Python, shell, C, awk ....) have the same issue when it use IEEE 754
  http://zh.wikipedia.org/zh-tw/IEEE_754
IEEE二進位浮點數算術標準(IEEE 754)是20世紀80年代以來最廣泛使用的浮點數運算標準,為許多CPU與浮點運算器所採用。這個標準定義了表示浮點數的格式(包括負零-0)與反常值(denormal number)),一些特殊數值(無窮(Inf)與非數值(NaN)),以及這些數值的「浮點數運算子」;它也指明了四種數值修約規則和五種例外狀況(包括例外發生的時機與處理方式)。


2. use below solution if you want to get result

2a: Math::BigFloat
2b: printf, sprintf
2c: use integer to do that

---------------------
use strict;
use warnings;
use Math::BigFloat;

my $n1 = 2.76;
my $n2 = 2.731;
my $d  = 1000;

my $x = Math::BigFloat->new($n1);

print $n1 - $n2, "\n";  # got some issue
print $x - $n2, "\n";   # 2a solution
printf("%.3f\n", $n1 - $n2); # 2b solution

print (($n1*$d - $n2*$d)/$d);  # 2c solution
作者: walklan    时间: 2014-01-26 16:31
提示: 作者被禁止或删除 内容自动屏蔽




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2