[英]Float to Double conversion - Best assertion in a unit test?
鉴于这些陈述
float f = 7.1f;
double d = f;
我们可以在单元测试中断言d?
例如,这不起作用:
Console.WriteLine(d == 7.1d); // false
Console.WriteLine(d < 7.1d + float.Epsilon); // true by luck
Console.WriteLine(d > 7.1d - float.Epsilon); // false (less luck)
我到目前为止找到的最好的方法是将值转换回来:
float f2 = (float)d;
Console.WriteLine(f2 == f); // true
这与粗野的说法相同
Console.WriteLine(d == 7.1f); // 7.1f implicitly converted to double as above
这个问题一般不是关于double和float精度的,而是关于单元测试如何最好地描述d的限制的实用问题。 在我的例子中,d是由轻量代码生成生成的代码中发生的转换的结果。 在测试这个代码生成时,我必须对这个函数的结果做出断言,这最终归结为上面的简单问题。
你的“最佳方式”是断言你生成的代码返回的内容是float
的误差范围7.1
。 这可能是你要检查的,在这种情况下,继续。
另一方面,您可能希望声明生成的代码特别返回将7.1f
转换为double
的结果,在这种情况下,您可以执行以下操作:
Console.WriteLine(d == (double)f);
这是更严格的 - 您的测试断言d
在一个小范围内,而上述测试断言d
是一个特定值。
这真的取决于你将使用什么d
。 如果事情出现问题,如果它不是确切的值,请测试确切的值,但如果可以在值的float
范围内,请检查float
。
为了比较两个浮点值ibm sugest来测试abs(a/b - 1) < epsilon
msnd指出,当实例的值为零时, Epsilon
属性反映了数值运算或比较中最重要的最小正值。
实际上你应该检查一下
Math.Abs(d/(double)f) - 1) < float.Epsilon)
(float) d == f
。
另一个答案建议d == (double) f
,但这是无用的测试,因为(double) f
执行与d = f
隐式执行的相同转换。 所以这个断言唯一可以测试的是实现的某些方面是否被破坏(例如,编译器错误地以不同的方式实现了其中一个转换),一些外部机制在赋值和之间改变了d
或f
。断言或源代码被破坏,因此d
既不是double
也不是float
也不是任何能够精确保存f
值或者没有执行赋值d = f
。
通常,我们期望没有浮点误差,因为在浮点的每个正常实现中,从较窄的精度到相同基数的更宽精度的转换没有错误,因为更宽的精度可以表示每个值,更窄的精度可以。 在不常见的情况下,较宽的浮点格式可能具有较小的指数范围。 只有在这种情况下,或者在反常定义的浮点格式中,转换为更宽的格式才会导致值的变化。 在这些情况下,执行相同的转换不会检测到更改。
相反,我们从更宽的格式转换回更窄的格式。 如果d
与f
不同,则此转换有可能检测到错误。 例如,假设f
包含0x1p-1000,但由于某种原因,这在d
的格式中是不可表示的,因此它被舍入为零。 然后(float) d == f
求值为(float) 0 == 0x1p-1000
,然后为0 == 0x1p-1000
,然后为false
。 另外,这种测试可以检测相同的错误,其他建议:一个破碎实施方式中,变更d
或f
,一个不正确的类型的d
,而且缺少分配d = f
。
除此之外,你会在这里用断言检测到什么错误?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.