簡體   English   中英

Clang和Visual C++之間的acos精度略有差異

[英]Slight acos precision difference between Clang and Visual C++

我有一些我正在使用的跨平台代碼。 在 Mac 上使用 Clang 編譯,在 Windows 上使用 Visual C++ 編譯。

有一個計算可能很敏感,Mac 和觸發斷言的 Windows 之間存在差異。 最終 acos 結果之間存在差異,但我不清楚為什么。

在這兩個平台上,acos 的輸入正好是 -1.0f。 在 Visual C++ 中, acos(-1.0f)為 3.14159274。 這就是 pi 作為浮點數的值,這是我所期望的。

但在 macOS 上:

float value = acos(-1.0f);

...計算為 3.1415925。 這足以觸發代碼中的問題的准確性差異。 acos 是一種使用浮點數可能不精確的操作 - 我明白這一點。 而且不同的編譯器可以有不同的acos實現。 我只是不清楚為什么 Clang 似乎對如此簡單的 acos 結果有問題,而 Visual C++ 沒有。 浮點數能夠表示 3.14159274,但這不是我得到的結果。

可以從 Xcode 的 Clang 版本中獲得准確/可視的 C++ 對齊值:

float value = (float)acos((double)-1.0f);

所以我可以通過提高精度來解決這個問題,然后將值向下轉換為浮點數以保持與 Windows 相同的舍入。 我只是在尋找一個理由,說明當 VC++ 編譯器似乎沒有精度問題時,為什么需要額外的精度。 也可能是 Clang/Xcode/VC++ 數學庫之間的差異。 我只是假設 acos(-1.0) 可能在編譯器中更穩定。 我找不到舍入模式的任何差異(即使不需要舍入),並且 Xcode 和 Visual Studio 中的新項目顯示出相同的差異。 兩台機器都是英特爾的。

如果您查看這些浮點值的二進制表示,您可以看到 mac/clang 的值A是比 windows/msvc 的值B的下一個最低浮點數

A    3.14159250    0x40490FDA
B    3.14159274    0x40490FDB

雖然 B 最接近 π 的真實值,但它實際上大於 π,正如 @njuffa 在他們的評論中指出的那樣。

閱讀規范,看起來acosf應該返回一個封閉范圍 [0,π] 內的值。 從技術上講A符合此標准,而B不符合。

總之 -

  • A是最接近但小於 π 的值
  • B是最接近 π 的值

這些差異可能是各個標准庫實現者深思熟慮的結果。

我還觀察到這兩個值都是cosf的真正倒數,因為cosf(A)cosf(B)都等於-1.0f

不過,一般來說,在任何浮點計算中依賴精確的位級精度是不明智的。 如果您還沒有意識到這一點,文檔What Every Computer Scientist Should Know About Floating-Point Arithmetic解釋了原因。


編輯:我很好奇,在這里找到了相關的 Apple 源代碼。

 Return value: ... Otherwise: ... Returns a value in [0, pi] (C 7.12.4.1 3). Note that this prohibits returning a correctly rounded value for acosf(-1), since pi rounded to a float lies outside that interval.

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM