如果我在C#中执行以下表达式:
double i = 10*0.69;
Run Code Online (Sandbox Code Playgroud)
i
是:6.8999999999999995
.为什么?
我理解像1/3这样的数字很难用二进制来表示,因为它有无限的重复小数位,但这不是0.69的情况.并且0.69可以很容易地用二进制表示,一个二进制数表示69,另一个表示小数位的位置.
我该如何解决这个问题?使用decimal
类型?
Jon*_*eet 156
因为您误解了浮点运算以及数据的存储方式.
事实上,在这种特定情况下,您的代码实际上并不执行任何算术 - 编译器将完成它,然后在生成的可执行文件中保存一个常量.但是,它不能存储6.9的精确值,因为该值不能以浮点值格式精确表示,就像1/3不能精确地存储在有限的十进制表示中一样.
Rus*_*een 53
为什么框架不能解决这个问题并将这个问题隐藏起来并给我正确答案,0.69 !!!
停止表现得像一个迪尔伯特经理,并接受计算机,虽然很酷,很棒,有限制.在您的具体情况下,它不仅仅是"隐藏"问题,因为您已经明确告诉它不要.语言(计算机)提供了您没有选择的格式的替代方案.你选择了double,它具有超过十进制的某些优点,以及某些缺点.现在,知道答案,你会感到不安的是,缺点不会神奇地消失.
作为程序员,您有责任隐藏管理者的这种缺点,并且有很多方法可以做到这一点.但是,C#的制造者有责任正确地使浮点工作,并且正确的浮点有时会导致错误的数学运算.
因此我们没有其他数字存储方法,因为我们没有无限位.我们作为程序员的工作是使用有限的资源来制作很酷的事情.他们在那里90%的路程,让火炬回家.
Kei*_*ith 15
并且0.69可以很容易地用二进制表示,一个二进制数表示69,另一个表示 小数位的位置.
我认为这是一个常见的错误 - 你正在考虑浮点数,好像它们是基数10(即十进制 - 因此我的重点).
所以 - 你认为这个双数有两个整数部分:69并除以100得到小数位移 - 这也可以表示为:
69 x 10到-2的幂.
然而,浮点数将"点的位置"存储为基数-2.
你的浮动实际上存储为:
68999999999999995 x 2到一个大负数的幂
一旦你习惯了,这并不是一个问题 - 大多数人都知道并期望1/3无法准确地表示为小数或百分比.只是不能用base-2表示的分数是不同的.
Cli*_*ord 11
但为什么框架不能解决这个问题并将这个问题隐藏起来并给我正确答案,0.69!
因为你告诉它使用二进制浮点,并且解决方案是使用十进制浮点,所以你建议框架应该忽略你指定的类型而不是使用十进制,这是非常慢的,因为它没有直接实现在硬件.
更有效的解决方案是不输出表示的完整值并明确指定输出所需的准确度.如果将输出格式化为两位小数,您将看到预期的结果.但是,如果这是一个财务应用程序十进制正是你应该使用的 - 你已经看到超人III(和Office Space)没有你;)
请注意,它只是无限范围的有限近似,它仅仅是十进制和双精度使用一组不同的近似值.十进制的优点是它会产生与您自己执行计算时相同的近似值.例如,如果你计算了1/3,那么当它"足够好"时你最终会停止写3.
要解决这个问题(例如显示在屏幕上),请尝试以下操作:
double i = (double) Decimal.Multiply(10, (Decimal) 0.69);
Run Code Online (Sandbox Code Playgroud)
大家似乎都回答了你的第一个问题,却忽略了第二部分。
归档时间: |
|
查看次数: |
21403 次 |
最近记录: |