当前位置: 首页 > 面试题库 >

为什么不使用Double或Float代表货币?

陆野
2023-03-14
问题内容

一直有人告诉我,永远不要用doublefloat类型来代表金钱,这一次我向您提出一个问题:为什么?

我敢肯定有一个很好的理由,我根本不知道这是什么。


问题答案:

因为浮点数和双精度数不能准确代表我们用于货币的基数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。

首先,将钱表示为double或float可能会很好地解决这个小错误,但是随着您对不精确的数字执行更多的加法,减法,乘法和除法,错误将会加重,最终您将得到明显的值不准确。这使得浮子和双子不足以应付金钱,在这种情况下,要求以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。 但我猜这些结果是相同的,但事实并非如此。 为什么结果不同?

  • 有人能给我一个例子,我如何在下面的代码中使用Double吗?

  • 问题内容: 我想知道为什么不推荐使用。 我曾经使用过JUnit 4.11。 下面是我的代码: 返回一个双精度值。 有什么事吗 问题答案: 由于double的精度问题而已弃用。 如果您注意到,还有另一种允许精度损失的方法。 JavaDoc: 断言两个双打等于正增量内。如果不是,则会引发AssertionError。如果期望值是无穷大,则将忽略增量值.NaN被视为相等:通过 … delta-期望值与实

  • 我想知道为什么不推荐使用。 我使用了导入静态组织。朱尼特。明确肯定资产质量 我使用了JUnit 4.11。 下面是我的代码: 返回一个双倍值。 有什么可能是错的?

  • 我有这个代码 但是由于上述代码的精度损失,我不得不通过为lat1、lon1、lat2、lon2提供BigDecimal而不是Double来更改它。但问题是如果我使用BigDecimal,我如何实现所有这些操作? 请指导我实现这一点 谢谢:)