[英]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.