正確避免浮點數計算偏差問題

转载 2012年03月22日 18:23:39
正確避免浮點數計算偏差問題
Filed Under : 业界博客 by admin
五.17,2011
来源博客:RichMedia+

不管是用哪一種語言,只要關於浮點數運算一定會出現偏差
譬如 AS3 or Javascript 執行 152.2938 * 100
會輸出 15229.380000000001
當然最精確的作法是改用大數 BigDecimal 類別

假如一般不需要用到那麼精確,又要避開浮點數運算偏差的問題
最常見的作法可能就是直接用浮點數乘 100,四捨五入之後再除以 100 了
網路上很多現成的 function 可以用

function roundFloat(value:Number, divider:Number):Number{
 return Math.round(value * divider) / divider;
}

問題來了,那個除數大小到底該怎樣決定呢?
你可能會覺得很簡單,需要精確到小數下兩位就用 100,精確到三位就用 1000

可是這樣的用法正確嗎?

雙精度浮點數有效位數是 15 位
整數位數多,小數有效位數就減少,反之亦然
倘若整數占了 13 位,算式精確到小數 3 位只是自己騙自己而已
倘若整數占了 3 位,算式精確到小數 3 位則是浪費浮點數的有效位數

很明顯固定抓小數 3 位的作法無法適用絕大部分情況
假如需要計算整數位數少,小數位數多情況
就增加 divider 參數,反之就要縮小 divider
無法用同一個算式計算大小不同的數值
這樣寫法實在有點笨

而且上面 function 內容真的很少,為了這問題
所有的地方都要 import 並呼叫這個 function
好像有點過頭了
倘若全部都改成 inline 的算式好像又顯得雜亂
畢竟每個地方用到的 divider 大小可能不一樣

以下分享一個更簡單的作法,且能更有效的利用浮點數所有的有效位數
利用 Number.toPrecision 指定轉成固定精確度 15 的字串
這樣一轉,有效位數的浮點數計算偏差就被去除掉了
然後再用 parseFloat 轉回浮點數

實際測試範例:

// 整數位數五位的情況,能夠進行到小數下 8 位的運算不受偏差影響
var no:Number = (152.2938 * 100) + 0.00000001;
trace(no);
// 15229.380000010002 <- 浮點數計算偏差
trace(parseFloat(no.toPrecision(15)));
// 15229.38000001 <- 修正浮點數計算偏差

// 整數位數 10 位的情況,能夠進行到小數下 3 位的運算不受偏差影響
var no:Number = 1234567890;
for (var i:int = 0 ; i < 9 ; ++i) {
 trace(no += 0.011);
 trace(no = parseFloat(no.toPrecision(15)));
}
/*/
1234567890.011
1234567890.011
1234567890.0219998  <- 浮點數計算偏差
1234567890.022      <- 修正浮點數計算偏差
1234567890.033
1234567890.033
1234567890.044
1234567890.044
1234567890.0549998  <- 浮點數計算偏差
1234567890.055      <- 修正浮點數計算偏差
1234567890.066
1234567890.066
1234567890.077
1234567890.077
1234567890.0879998  <- 浮點數計算偏差
1234567890.088      <- 修正浮點數計算偏差
1234567890.099
1234567890.099
//*/

除了 Number.toPrecision 之外也可以使用 Number.toExponential
trace(Number(no.toExponential(15)));

以上的方式簡單到根本沒有必要獨立寫成一個 function,也不需要設置不同參數
一律 inline 使用就好了

Related posts:

    Flex 3 Style Module
    Flex 4 Style Module
    Create Trail Information & Expired Date in ActionScript3 & Flex


JS的浮点数计算精度丢失问题解决方案

近期在做项目的时候,遇到了一些JS浮点数精度的问题。这个问题,其实说大不大,说小不小。但是这次因为涉及到一些财务和结算的问题,然后突然发现这个小问题处理起来还是挺麻烦的。这里把相关的原因的问题的解决方...

js浮点数精度问题(js计算中遇到的坑)

转自:http://talentluke.iteye.com/blog/1767138 大多数语言在处理浮点数的时候都会遇到精度问题,但是在JS里似乎特别严重,来看一个例子 alert(4...
  • DADADIE
  • DADADIE
  • 2015年12月23日 10:44
  • 7885

Java浮点数float和double精确计算的精度误差问题总结

http://blog.csdn.net/aya19880214/article/details/45891581 float和double只能用来做科学计算或者是工程计算,在商...

【讨论】为啥0.2+0.4 != 0.6(浮点数计算的精度问题)

【讨论】为啥0.2+0.4 != 0.6(浮点数计算的精度问题)   网上有很多帖子讨论浮点数的精度问题,其中有如下命题: 0.2+0.4=0.600 000 000 000 0...

报告一个IE很奇葩的滚动条问题——百分比计算宽度为浮点数时的滚动条显示异常

起因:   做项目的时候做了一个表格内容超过DIV容器自动横向滚动处理。别的浏览器都正常;但是在IE下面明明表格table和容器DIV宽度一致但是却出现了滚动条。如图      然后本人做实验找...

Java 浮点数计算问题

Java 浮点数计算问题

java中floatdouble浮点数的计算失精度问题

java中浮点数的计算今天在数值计算时碰到一个问题.程序如下:  double a = (3.3-2.4)/0.1;  System.out.println(a);你可能认为结果很简单,不就是9嘛,是...

Java浮点数float和double精确计算的精度误差问题总结

转载于:http://blog.csdn.net/aya19880214/article/details/45891581 1、float整数计算误差 案例:会员积分字段采用float...

【Java】解决计算浮点数精度问题(BigDecimal)

工具类如下: import java.math.BigDecimal; /** * * @ClassName: ArithUtils * @Description: 数学计算工...
  • hj7jay
  • hj7jay
  • 2016年09月05日 22:13
  • 1405

php中浮点数计算问题

如果用php的+-*/计算浮点数的时候,可能会遇到一些计算结果错误的问题,比如echo intval( 0.58*100 );会打印57,而不是58,这个其实是计算机底层二进制无法精确表示浮点数的一个...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:正確避免浮點數計算偏差問題
举报原因:
原因补充:

(最多只允许输入30个字)