所以做一个print(0.3 - 0.2);会打印0.09999999999999998。
我知道浮点运算对于二进制处理器来说是不可能正确的,但我希望 Dart 中内置的一些东西至少会尝试消除舍入错误。
使上面显示 0.1 需要来回进行一些转换,我宁愿不这样做:
print(num.parse((0.3 - 0.2).toStringAsPrecision(8)));
-> 0.1
Run Code Online (Sandbox Code Playgroud)
我有什么选择可以不让小数变得疯狂?Dart 中是否有任何内置功能可以帮助解决此问题?似乎只有一个库可以执行上述操作:https : //pub.dev/packages/decimal?
您可以通过以下方式将值四舍五入为十的倍数(或任何其他数字):
double roundTo(double value, double precision) => (value * precision).round() / precision;
Run Code Online (Sandbox Code Playgroud)
然后,您可以对初始值或最终结果执行此操作:
int precision = 10;
final result = roundTo(0.3 - 0.2, precision);
// or inlined:
final result = ((0.3 - 0.2) * precision).round() / precision;
Run Code Online (Sandbox Code Playgroud)
这可确保对原始值进行计算,并且您只对最终结果进行四舍五入。
如果您知道您的输入值都具有相同的比例,您可以按照@brian-gorman 的建议进行操作并首先缩放值,然后最后舍入和缩小结果。对于这种用途,我建议尽早对传入的值进行舍入,以便计算不会累积不精确。(这对于单个减法无关紧要,但对于更复杂的计算,它可能)。
final difference = (0.3 * precision).round() - (0.2 * precision).round();
final result = difference / precision;
Run Code Online (Sandbox Code Playgroud)
记录:您看到的结果不是舍入错误,而是正确的结果 - 对于 IEEE-754 定义的 64 位浮点数。
您将在使用普通双精度的任何其他语言(包括 JavaScript 和 Java)中看到相同的结果。的结果0.3 - 0.2 不是表示为 的双精度值0.1。它是一个不同的数字,因此它必须具有不同的toString表示形式。
0.1、0.2 或 0.3 都不能准确地表示为双打。实际值为:
0.1 : 0.1000000000000000555111512312578270211815834045410156250.2 : 0.2000000000000000111022302462515654042363166809082031250.3 : 0.299999999999999888977697537484345957636833190917968750.3 - 0.2 : 0.09999999999999997779553950749686919152736663818359375因此,当您编写语法 0.3and 时0.2,您实际上是在指定上面的精确双精度值。
结果变成这样,因为 0.3 - 0.2 的精确数学计算是
0.299999999999999988897769753748434595763683319091796875
- 0.200000000000000011102230246251565404236316680908203125
= 0.099999999999999977795539507496869191527366638183593750
Run Code Online (Sandbox Code Playgroud)
结果是一个精确的双精度值。所以结果 0.09999... 正是“0.3”和“0.2”之间的差,因此是减法的正确结果。(错误是假设您实际上将 0.3 和 0.2 作为值,而您从未这样做过)。它也没有为数字表示由0.1是相同的。
| 归档时间: |
|
| 查看次数: |
494 次 |
| 最近记录: |