[英]Different results from similar floating-point functions
所以我有2個功能應該做同樣的事情
float ver1(float a0, float a1) {
float r0 = a0 - a1;
if (abs(r0) > PI) {
if (r0 > 0) {
r0 -= PI2;
} else {
r0 += PI2;
}
}
return r0;
}
float ver2(float a0, float a1) {
float a2 = a1 - PI2;
float r0 = a0 - a1;
float r1 = a0 - a2;
if (abs(r0) < abs(r1)) {
return r0;
}
if (abs(r0) > abs(r1)) {
return r1;
}
return 0;
}
注意:PI和PI2是pi和2 * pi的浮點常量
奇怪的是,有時它們會產生不同的結果,例如,如果喂入它們0.28605145和5.9433694,則第一個結果為0.62586737,第二個結果為0.62586755,我無法弄清楚是什么原因引起的。
如果您手動計算結果應該是什么,您會發現第二個答案是正確的。 我在2d物理模擬中使用了此功能,真正奇怪的是,第一個答案(錯誤的答案)在那里起作用,而第二個答案(正確的答案)使它表現得很瘋狂。 與未知來源的微小差異和如此深遠的影響:|
此時我還是會切換到矩陣,但是這種奇怪的情況讓我感到好奇,有人知道發生了什么嗎?
float
通常具有約24位或約7個小數位的精度。
您要減去兩個幅度相似的數字(第一個為r0+PI2
,第二個為a1-PI2
),因此正經歷有效度損失 -結果的幾個最高有效位為零,因此剩下的位更少代表差異。 這就是為什么答案僅匹配約6個小數位的原因。
如果需要更高的精度,則double
精度或32位或更大的定點表示可能比float
更合適。 還有一些可用的任意精度庫,例如GMP ,它可以用您需要的所有精度來表示數字,盡管算術比內置類型慢得多。
您應該使用fabs()
函數而不是abs()
因為abs()
僅適用於整數。 當使用帶有浮點數的abs()
時,會得到奇怪和錯誤的結果。
浮點數的行為不像數學實數。 每加2可能會導致“錯誤”。 所以我不會僅僅因為一個例子就稱第一個正確和第二個不正確。 如果要使錯誤保持較小,則需要注意對float進行的每個操作。
如果數字的絕對值在相同范圍內,則誤差通常較小。 如果范圍不同,則誤差會更大。
例如10000000.0 + 0.1 - 10000000.0
幾乎不會是0.1
。
如果知道輸入范圍,則可以調整代碼以減少錯誤。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.