【问题标题】:Abs(0.33-0.99)=0.6599999999 Why? [duplicate]Abs(0.33-0.99)=0.6599999999 为什么? [复制]
【发布时间】:2014-03-28 16:58:03
【问题描述】:

java 中运行 kmeans 聚类时,数据点 0.33 和 0.99 之间的绝对差值显示为 0.659999999 而不是 0.66。

为什么会这样?

保存数据的两个变量都是double 类型,我正在使用Math.abs() 函数。

我只在 0.99 中看到过这样的问题。使用其他值相减时,结果很好。

感谢您的帮助

【问题讨论】:

  • 参见Floating Point Arithmetic: Issues and Limitations - 文章来自 Python 文档,但问题与语言无关。二进制浮点数在很多情况下无法准确存储十进制浮点数。
  • 这个视频很好地解释了这一点。 youtube.com/watch?v=PZRI1IfStY0
  • @Jakob:即使是你的算盘(还有你的手指和脚趾)也只有有限数量的可用位;-P
  • @JensG 是的,但是用我的手指添加会得到正确的结果,而不是 1 个手指 + 1 个手指 = 1.99999899 个手指 :)
  • 永远永远永远,无论如何永远!

标签: java floating-point absolute


【解决方案1】:

浮点数据类型(float 和 double)无法在内存位中准确表示。它们在内存中大致表示。

将无限多个实数压缩为有限位数 需要一个近似的表示。虽然有无限 许多整数,在大多数程序中整数计算的结果可以 以 32 位存储。相反,给定任何固定数量的比特, 大多数实数计算将产生的数量 不能用那么多位精确表示。因此 浮点计算的结果通常必须按顺序四舍五入 以适应其有限的表示。这个舍入误差是 浮点计算的特征

What Every Computer Scientist Should Know About Floating-Point Arithmetic

【讨论】:

  • 如果你不介意,你能解释一下为什么Math.abs(new Float(0.33-0.99))返回0.66吗?
【解决方案2】:

这就是浮点数的行为方式。它们不准确。

检查这个:- What Every Computer Scientist Should Know About Floating-Point Arithmetic

还要添加浮点数使用二进制分数而不是十进制分数。如果你需要精确的十进制值,你应该使用java.math.BigDecimal

您也可以查看answer 了解更多推理和详细信息:

浮点舍入错误。 0.1 不能表示为 由于缺少主要因子 5.

【讨论】:

    【解决方案3】:

    由于它们在内存中的存储方式,双精度值并不精确。更多信息在这里: https://en.wikipedia.org/wiki/Double-precision_floating-point_format

    如果您需要准确的结果,您应该查看BigDecimal

    【讨论】:

    • BigDecimal 并不比 double 更精确。它仅适用于一组不同的数字。
    • 你能支持这个说法吗?因为,据我所知, BigDecimal 更准确。来自文档:“当为 MathContext 对象提供精度设置为 0(例如,MathContext.UNLIMITED)时,算术运算是精确的,就像不采用 MathContext 对象的算术方法一样。”
    • 注意:我没有说这不是“更准确”。我说它对于与double 不同的一组数字是精确的(double 对于很多数字都是精确的,如果你知道自己在做什么,可以进行长序列精确的double 计算),并且“如果你需要一个准确的结果,你应该研究 BigDecimal”是一种错误的描述。让我这样说吧:我想要 1 除以 3 的确切结果。对于这个基本运算,“查看 BigDecimal”是浪费时间。它不会起作用。
    • 点了。 “在除法的情况下,精确商可能有无限长的十进制扩展;例如,1 除以 3。如果商具有非终止十进制扩展并且指定操作返回精确结果,则会引发 ArithmeticException。 " - 但是,您可以指定要查看的小数位数(最多 4679 位,我已经测试过),使其比 Double 精确得多。
    • 您的意思是“远比双精度”。表示要么准确,要么不准确。
    猜你喜欢
    • 2011-02-02
    • 1970-01-01
    • 1970-01-01
    • 2021-08-06
    • 2014-02-18
    • 2012-02-28
    • 2019-09-18
    • 2012-06-21
    • 1970-01-01
    相关资源
    最近更新 更多