代码之家  ›  专栏  ›  技术社区  ›  Dan TheCodeJunkie

.NET中的乘法是否中断?[复制品]

  •  51
  • Dan TheCodeJunkie  · 技术社区  · 15 年前

    这个问题已经有了答案:

    如果我在C中执行以下表达式:

    double i = 10*0.69;
    

    i 是: 6.8999999999999995 .为什么?

    我知道像1/3这样的数字很难用二进制表示,因为它有无限个重复出现的小数位,但这不是0.69的情况。0.69可以很容易地用二进制表示,一个二进制数表示69,另一个二进制数表示小数点的位置。

    我怎么解决这个问题?使用 decimal 类型?

    6 回复  |  直到 11 年前
        1
  •  156
  •   Community CDub    12 年前

    因为你误解了浮点运算和数据的存储方式。

    事实上,在这种特殊情况下,您的代码在执行时实际上没有执行任何算术-在 编译程序 将执行此操作,然后在生成的可执行文件中保存常量。然而,它 不能 存储6.9的精确值,因为该值不能以浮点格式精确表示,就像1/3不能以有限的十进制表示精确存储一样。

    看看是否 this article 帮助你。

        2
  •  53
  •   Russell Steen    13 年前

    为什么框架不能解决这个问题,并对我隐瞒这个问题,给我 回答正确,0.69!!!!

    别再表现得像个呆伯特的管理者了,接受电脑虽然很酷,但也有局限性。在您的具体案例中,它不仅仅是“隐藏”问题,因为您已经明确告诉它不要这样做。语言(计算机)提供了您没有选择的格式的替代方案。您选择了double,它比decimal有一定的优势,也有一定的缺点。现在,知道答案后,你会为自己的缺点不会神奇地消失而心烦意乱。

    作为一个程序员,你有责任向管理者隐瞒这个缺点,而且有很多方法可以做到这一点。然而,C的制造商有责任使浮点正确工作,正确的浮点偶尔会导致错误的数学。

    其他的数字存储方法也是如此,因为我们没有无限位。作为程序员,我们的工作是使用有限的资源来实现酷的事情。他们把你带到90%的地方,把火炬拿回家。

        3
  •  15
  •   Keith    15 年前

    0.69可以很容易地表示为 二进制,69和 另一个表示 十进制的 地点。

    我认为这是一个常见的错误——你把浮点数看成是以10为基数的数字(即十进制——因此我强调了这一点)。

    所以-你认为这个双引号有两个整数部分: 六十九 除以100 移动小数点-也可以表示为:
    69 x 10到-2的幂 .

    然而,浮点数将“点的位置”存储为 二元数 .

    您的浮动实际上存储为:
    68999999999995 x 2为某个大负数的幂

    一旦你习惯了这一点,这就不再是一个问题了——大多数人都知道并期望1/3不能准确地表示为小数或百分比。只是不能用基2表示的分数是不同的。

        4
  •  11
  •   Clifford    11 年前

    但是为什么框架不能解决这个问题,把这个问题隐藏起来,给我一个正确的答案,0.69!!!!

    因为你让它用 二进制浮点 ,解决方案是使用 十进制浮点 ,因此您建议框架应忽略指定的类型并使用 十进制的 相反,这是非常慢的,因为它不是直接在硬件中实现的。

    更有效的解决方案是不输出表示的完整值,并显式指定输出所需的精度。如果将输出格式化为两个小数位,您将看到预期的结果。但是,如果这是一个财务应用程序 十进制的 正是你应该使用的——你见过超人III(和办公空间),不是吗;)

    注意,它都是无限范围的有限近似值,只是 十进制的 双重的 使用一组不同的近似值。的优势 十进制的 它产生的近似值是否与您自己进行计算时的近似值相同?例如,如果你计算了1/3,你最终会在“足够好”的时候停止写3。

        5
  •  8
  •   erikkallen    15 年前

    由于同样的原因,十进制中的1/3表示为0.33333333333333333333333333333333333333333333333333333333333333333333,而不是无限长的精确分数。

        6
  •  2
  •   Richard    11 年前

    要解决此问题(例如在屏幕上显示),请尝试以下操作:

    double i = (double) Decimal.Multiply(10, (Decimal) 0.69);
    

    似乎每个人都回答了你的第一个问题,但忽略了第二部分。