人们总是被告知永远不要用double
或float
类型代表金钱,这一次我向您提出一个问题:为什么?
我敢肯定有一个很好的理由,我根本不知道这是什么。
因为浮点数和双精度数不能准确表示我们用于赚钱的基数10的倍数。这个问题不仅仅针对Java,而且还针对任何使用base 2浮点类型的编程语言。
在基数10中,您可以将10.25编写为1025 * 10 -2(整数乘以10的幂)。IEEE-754浮点数是不同的,但是考虑它们的一种非常简单的方法是乘以2的幂。例如,您可能正在查看164 * 2 -4(整数乘以2的幂),它也等于10.25。这不是数字在内存中的表示方式,但是数学含义是相同的。
即使在基数10中,该符号也不能准确表示最简单的分数。例如,您不能表示1/3:十进制表示形式正在重复(0.3333 …),因此没有可以乘以10的幂来获得1/3的有限整数。您可以使用3的长序列和较小的指数,例如333333333 * 10 -10,但这是不准确的:如果将其乘以3,则不会得到1。
但是,出于数钱的目的,至少对于货币价值在美元数量级内的国家而言,通常您所需要的只是能够存储10 -2的倍数,因此这并不重要不能代表1/3。
浮点数和双精度数的问题在于,绝大多数类似货币的数字都不能精确表示为整数乘以2的幂。实际上,0和1之间只有0.01的倍数(在交易时很重要)可以用货币表示,因为它们是整数美分),可以完全表示为IEEE-754二进制浮点数,分别为0、0.25、0.5、0.75和1。所有其他值相差很小。类似于0.333333的示例,如果将浮点值设为0.1,然后将其乘以10,则不会得到1。
首先,将钱表示为doubleorfloat
可能会很好地解决这个小错误,但是随着您对不精确的数字执行更多的加法,减法,乘法和除法运算,错误将会加重,最终您将得到明显的值不准确。这使得浮子和双子不足以处理金钱,在这种情况下,需要十进制乘以10的幂的完美精度。
适用于几乎所有语言的解决方案是改用整数,然后计算分。例如,1025为$ 10.25
。几种语言还具有内置类型来处理金钱。其中,Java具有BigDecimal
类,而C#
具有decimal
类型。
问题内容: 一直有人告诉我,永远不要用或类型来代表金钱,这一次我向您提出一个问题:为什么? 我敢肯定有一个很好的理由,我根本不知道这是什么。 问题答案: 因为浮点数和双精度数不能准确代表我们用于货币的基数10的倍数。这个问题不仅仅针对Java,而且还针对任何使用base 2浮点类型的编程语言。 在基数10中,您可以将10.25编写为1025 * 10 -2(整数乘以10的幂)。IEEE-754浮点
我理解为0.1d+0.2d~=0.300000000000000004。 但我猜这些结果是相同的,但事实并非如此。 为什么结果不同?
问题内容: 我想知道为什么不推荐使用。 我曾经使用过JUnit 4.11。 下面是我的代码: 返回一个双精度值。 有什么事吗 问题答案: 由于double的精度问题而已弃用。 如果您注意到,还有另一种允许精度损失的方法。 JavaDoc: 断言两个双打等于正增量内。如果不是,则会引发AssertionError。如果期望值是无穷大,则将忽略增量值.NaN被视为相等:通过 … delta-期望值与实
我想知道为什么不推荐使用。 我使用了导入静态组织。朱尼特。明确肯定资产质量 我使用了JUnit 4.11。 下面是我的代码: 返回一个双倍值。 有什么可能是错的?
本文向大家介绍float 和 double 的区别是什么?相关面试题,主要包含被问及float 和 double 的区别是什么?时的应答技巧和注意事项,需要的朋友参考一下 float 最多可以存储 8 位的十进制数,并在内存中占 4 字节。 double 最可可以存储 16 位的十进制数,并在内存中占 8 字节。
问题内容: 我已经在Android代码中使用FloatBuffers一段时间了(从一些opengles教程中复制了它),但是我无法确切地理解此构造是什么以及为什么需要它。 例如,我在许多人的代码和android教程中看到了以下代码(或类似代码): 就我所知,这似乎是冗长和混乱的,我只是说它们只是一个浮点数的包装而已。 问题: 与任何其他类型的float集合或简单数组相反,这种类型的类(ByteBu