.NET上的双精度问题
我有一个简单的C#函数:
public static double Floor(double value, double step) { return Math.Floor(value / step) * step; }
计算更高的数字,低于或等于“值”,即“步数”的倍数。 但它缺乏精确性,如下面的测试所示:
[TestMethod()] public void FloorTest() { int decimals = 6; double value = 5F; double step = 2F; double expected = 4F; double actual = Class.Floor(value, step); Assert.AreEqual(expected, actual); value = -11.5F; step = 1.1F; expected = -12.1F; actual = Class.Floor(value, step); Assert.AreEqual(Math.Round(expected, decimals),Math.Round(actual, decimals)); Assert.AreEqual(expected, actual); }
第一个和第二个断言都可以,但第三个断言失败,因为结果只等到第6个小数位。 这是为什么? 有没有办法纠正这个?
更新如果我调试测试,我看到值相等,直到第8个小数位而不是第6个,可能是因为Math.Round引入了一些不精确。
注意在我的测试代码中,我写了“F”后缀(显式浮点常量),其中我的意思是“D”(双),所以如果我改变它,我可以有更多的精度。
如果省略所有F后缀(即-12.1
而不是-12.1F
),您将获得更多相等的几位数。 由于F
您的常量(尤其是预期值)现在是浮点数。 如果您是故意这样做,请解释。
但是对于其余的我同意比较双重或浮动值的平等的其他答案,它只是不可靠。
计算机上的浮点运算不是Exact Science :)。
如果您希望精确到预定义的小数位数,请使用Decimal而不是double或接受小间隔。
我实际上希望他们没有为浮点数和双精度数实现==运算符。 要问一个double或float是否等于任何其他值,几乎总是错误的做法。
https://en.wikipedia.org/wiki/Floating_point#Accuracy_problems
例如,0.1和0.01的不可表示性(二进制)意味着尝试平方0.1的结果既不是0.01也不是最接近它的可表示数。
如果您需要机器对数字系统的解释(二进制),请仅使用浮点。 你不能代表10美分。
如果需要precision,请使用System.Decimal。 如果需要速度,请使用System.Double(或System.Float)。 浮点数不是“无限精度”数,因此断言相等必须包括容差。 只要您的数字具有合理的有效位数,就可以了。
请参阅这个答案(也是我),详细分析精度如何影响数学运算的结果。
检查此问题的答案: 将浮点值的相等性检查为0是否安全?
真的,只需检查“在……的容忍范围内”
浮动和双打不能准确存储所有数字。 这是IEEE浮点系统的限制。 为了获得忠实的精确度,您需要使用更高级的数学库。
如果你不需要超过某一点的精度,那么也许十进制对你来说会更好。 它具有比双精度更高的精度。
对于类似的问题,我最终使用以下实现,这似乎是我的大多数测试用例(最多5位精度)的成功:
public static double roundValue(double rawValue, double valueTick) { if (valueTick <= 0.0) return 0.0; Decimal val = new Decimal(rawValue); Decimal step = new Decimal(valueTick); Decimal modulo = Decimal.Round(Decimal.Divide(val,step)); return Decimal.ToDouble(Decimal.Multiply(modulo, step)); }
有时结果比您对严格要求的结果更精确:FP IEEE 754.这是因为HW使用更多位进行计算。 请参阅C#规范和本文
Java有strictfp关键字,C ++有编译器开关。 我想念.NET中的这个选项
上述就是C#学习教程:.NET上的双精度问题分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注---计算机技术网(www.ctvol.com)!
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/1013318.html