由浮点数的精度问题引出设计问题

本文由ruby-china的一篇帖子“由小数的精度问题引出设计问题”引出,帖子也是我发的,在查看回复的时候学到了不少内容,有了一点感悟,所以就想总结一下。

首先声明本文选用的编程语言为ruby,运行环境是ubuntu。

在编写财务,电子商务之类应用的时候,经常会碰到小数,小数乘、除、加、减的场景。

大多数语言表示小数,都有单精度float,双精度double,还有一个更加精确的decimal,无论是哪一种,都统称为浮点数。

浮点数是一个近似的数值,不是精确的数值。至于为什么不精确,这个涉及到操作系统的底层,和二进制的保存有关。关于浮点数,以及浮点数计算产生精度损失的内容可以参看下面几篇文章。

浮点数

定点数与浮点数的区别

避免对C#中float,double,decimal的错误理解

浮点数操作精度损失

浮点数的比较

浮点数的四则运算都会有精度损失问题,会导致浮点数的逻辑运算结果超出日常生活的认识。

常见问题:

irb(main):005:0> 1.3-1.0 == 0.3
=> false

颠覆了我们生活中的常识,因为在计算机中1.3-1.0的结果是 0.30000000000000004。

还有就是d * g / g 不一定等于d, d / g * g也不一定等于d。

这就造成,在很多时候,不能使用==来直接比较两个浮点数,因为浮点数不是精确数值,而是一个近似值。

怎么办呢?

既然是近似值,就是说他们两个非常接近,差距也就是0.00000000001之类的,反正很小。我们可以利用这个特性,写一个我们的两个浮点数比较的函数。只要我们确认两个浮点数之间的差距小到一个我们可以接受的值,就认为这两个浮点数是相等的。比如我们定义只要小于0.000000001,就算这两个浮点数是相等的,就可以写出下面的代码。

module FloatEqual
  def equal(b)
    return self==b || (self-b).abs < 0.000000001
  end
end 

(1.3-1.0).extend(FloatEqual).equal(0.3) # true

还有一个就是Saito在帖子中提到的一个方案,整数比较法。什么是整数比较法呢?就是将比较的双方都换算成整数,准确的说,就是双方都放大10倍,或者100倍,或者1000倍,反正就是放大同样的倍数,保证双方都是整数,这时候再来计算,再来比较。

为什么呢?因为整数的保存不存在精度损失问题,整数的四则运算不存在精度损失问题,所以计算结果的比较就可以是正确的,可以直接用==来比较了,

(1.3*10 - 1.0*10) == 0.3*10 # true

在ruby中还可以使用BigDecimal来比较浮点数,或者进行浮点数的四则运算,也可以避免精度损失导致的问题。

BigDecimal.new("1.3")-BigDecimal.new("1")==BigDecimal.new("0.3") # true

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索问题
, bigdecimal
, 浮点数
, 浮点数运算
, 精度
, 整数
, 小数
, 运算放大
, double精度问题
, 浮点数的问题
, 计算精度
, #浮点数
, 一个
点数
浮点数精度问题、浮点数计算精度问题、js浮点数精度问题、java 浮点数精度问题、双精度浮点数,以便于您获取更多的相关知识。

时间: 2024-08-11 11:33:07

由浮点数的精度问题引出设计问题的相关文章

PHP浮点数运算精度的问题

在用PHP进行浮点数的运算中,遇到一个坑,没有得到预期中的结果,如下代码: $a = 69.1;   $b = $a*100;   $c = $b-6910; 你猜$c的值是多少?$c输出的值是-9.0949470177293E-13.为什么会这样? 在PHP官网Float浮点型页面中,讲到: 浮点数的精度 浮点数的精度有限.尽管取决于系统,PHP 通常使用 IEEE 754 双精度格式,则由于取整而导致的最大相对误差为 1.11e-16.非基本数学运算可能会给出更大误差,并且要考虑到进行复合运

解决Javascript浮点数相乘精度问题

例子1 基本的思想就是把浮点数全部变成整数,然后除以等值的10的N阶次方.N为(两个浮点数的后面长度之和).  代码如下 复制代码 function FxF(f1, f2) {     f1 += '';     f2 += '';     var f1Len = f1.split('.')[1].length,         f2Len = f2.split('.')[1].length;     if (f1Len) {         f1 = f1.replace('.', '');

JavaScript 浮点数运算 精度问题_javascript技巧

Js代码 复制代码 代码如下: <script type="text/javascript" language="javascript"> alert(1/3);//弹出: 0.3333333333333333 alert(0.09999999 + 0.00000001);//弹出: 0.09999999999999999 alert(-0.09999999 - 0.00000001);//弹出: -0.09999999999999999 alert(0

代码之谜(五)- 浮点数(谁偷了你的精度?)

如果我告诉你,中关村配置最高的电子计算机的计算精度还不如一个便利店卖的手持计算器,你一定会反驳我:「今天写博客之前又忘记吃药了吧」. 你可以用最主流的编程语言计算 0.2 + 0.4,如果你使用的是 Chrome.FireFox.IE 8+,可以按 F12 键,然后找到 「控制台」,输入上面的 表达式 0.2 + 0.4,回车. 然后再用最简陋的计算器(如果你没有手持计算器没关系,手机.电脑都自带一个计算器,打开"运行",输入 calc,回车) 再计算一下刚才的 算式 0.2 + 0.

PHP浮点数精度问题汇总

  这篇文章主要介绍了PHP浮点数精度问题汇总,本文着重探讨PHP浮点数精度损失问题,用三个段落不同的方式讲解了这个问题的形成原因以及解决方法,需要的朋友可以参考下 一.PHP浮点数精度损失问题 先看下面这段代码: 代码如下: $f = 0.57; echo intval($f * 100); //56 结果可能有点出乎你的意外,PHP遵循IEEE 754双精度: 浮点数, 以64位的双精度, 采用1位符号位(E), 11指数位(Q), 52位尾数(M)表示(一共64位). 符号位:最高位表示数

Java之道系列:BigDecimal如何解决浮点数精度问题

如题,今天我们来看下java.math.BigDecimal是如何解决浮点数的精度问题的,在那之前当然得先了解下浮点数精度问题是什么问题了.下面我们先从IEEE 754说起. IEEE 754 IEEE二进制浮点数算术标准(IEEE 754)是20世纪80年代以来最广泛使用的浮点数运算标准,为许多CPU与浮点运算器所采用.这个标准定义了表示浮点数的格式(包括负零-0)与反常值(denormal number)),一些特殊数值(无穷(Inf)与非数值(NaN)),以及这些数值的"浮点数运算符&qu

PHP浮点数精度问题汇总_php技巧

一.PHP浮点数精度损失问题 先看下面这段代码: 复制代码 代码如下: $f = 0.57; echo intval($f * 100);  //56 结果可能有点出乎你的意外,PHP遵循IEEE 754双精度: 浮点数, 以64位的双精度, 采用1位符号位(E), 11指数位(Q), 52位尾数(M)表示(一共64位). 符号位:最高位表示数据的正负,0表示正数,1表示负数. 指数位:表示数据以2为底的幂,指数采用偏移码表示 尾数:表示数据小数点后的有效数字. 再来看看小数用二进制怎么表示:

JavaScript浮点数及运算精度调整详解_javascript技巧

JavaScript 只有一种数字类型 Number,而且在Javascript中所有的数字都是以IEEE-754标准格式表示的.浮点数的精度问题不是JavaScript特有的,因为有些小数以二进制表示位数是无穷的. 十进制       二进制 0.1              0.0001 1001 1001 1001 - 0.2              0.0011 0011 0011 0011 - 0.3              0.0100 1100 1100 1100 - 0.4 

JavaScript 浮点数及运算精度调整总结

JavaScript 只有一种数字类型 Number,而且在Javascript中所有的数字都是以IEEE-754标准格式表示的.浮点数的精度问题不是JavaScript特有的,因为有些小数以二进制表示位数是无穷的. 十进制       二进制 0.1              0.0001 1001 1001 1001 - 0.2              0.0011 0011 0011 0011 - 0.3              0.0100 1100 1100 1100 - 0.4