簡體   English   中英

使用C11和GNU11編譯器標志的機器epsilon計算有所不同

[英]Machine epsilon calculation is different using C11 and GNU11 compiler flags

當使用Python和Julia時,我可以使用一種巧妙的技巧來研究機器epsilon的特定浮點表示形式。

例如,在Julia 1.1.1中:

julia> 7.0/3 - 4/3 - 1
2.220446049250313e-16 

julia> 7.0f0/3f0 - 4f0/3f0 - 1f0
-1.1920929f-7

我目前正在學習C,並編寫了此程序來嘗試實現相同的目的:

#include <stdio.h>

int main(void)
{
  float foo;
  double bar;

  foo = 7.0f/3.0f - 4.0f/3.0f - 1.0f;
  bar = 7.0/3.0 - 4.0/3.0 - 1.0;

  printf("\nM.E. for float: %e \n\n", foo);
  printf("M.E. for double: %e \n\n", bar);

  return 0;
}

奇怪的是,我得到的答案取決於我使用的是C11還是GNU11編譯器標准。 我的編譯器是GCC 5.3.0,可在Windows 7上運行並通過MinGW安裝。

簡而言之,當我編譯時: gcc -std=gnu11 -pedantic begin.c我得到:

M.E. for float: -1.192093e-007

M.E. for double: 2.220446e-016

如我所料,並且與Python和Julia相匹配。 但是當我編譯時: gcc -std=c11 -pedantic begin.c我得到:

M.E. for float: -1.084202e-019

M.E. for double: -1.084202e-019

這是意外的。 我認為可能是因為GNU的特定功能,這就是為什么我添加-pedantic標志的原因。 我一直在Google上搜索,發現以下內容: https : //gcc.gnu.org/onlinedocs/gcc/C-Extensions.html,但我仍然無法解釋行為上的差異。

明確地說,我的問題是: 為什么使用不同的標准會導致結果不同?

更新:相同的區別適用於C99和GNU99標准。

在C語言中,獲取floatdouble epsilon的最佳方法是包含<float.h>並使用FLT_MINDBL_MIN

7.0/3.0 - 4.0/3.0 - 1.0; C標准沒有完全指定它,因為它允許實現比標稱類型更精確地評​​估浮點表達式。 在某種程度上,這可以通過使用強制轉換或分配來解決。 C標准要求強制轉換或分配以“放棄”多余的精度。 通常,這不是一個合適的解決方案,因為可以用初始的多余精度和“舍棄”多余精度的操作進行舍入。 與完全以標稱精度進行計算相比,這種兩次舍入可能會產生不同的結果。

將強制轉換方法與問題中的代碼一起使用將產生:

_Static_assert(FLT_RADIX == 2, "Floating-point radix must be two.");
float FloatEpsilon = (float) ((float) (7.f/3) - (float) (4.f/3)) - 1;
double DoubleEpsilon = (double) ((double) (7./3) - (double) (4./3)) - 1;

請注意,需要靜態聲明來確保浮點基數符合此kudge操作的預期。 該代碼還應包括說明此錯誤主意的文檔:

  • 分數⅓的二進制表示形式以“ 01010101…”的無限序列結尾。
  • 將4/3或7/3的二進制數四舍五入到固定精度時,就好像數字被截斷並向下或向上舍入一樣,這取決於截斷后的下一個二進制數字是0還是1。
  • 假設我們的浮點數使用一個以2為基數的基數,則4/3和7/3處於連續二進制中(4/3位於[1,2]中,而7/3位於[2,4]中)。 因此,它們的截斷點相距一個位置。
  • 因此,我們轉換為二進制浮點格式時,4/3和7/3的不同之處在於后者比前者大1,並且其有效位數早一點結束。 對可能的截斷點的檢查表明,除了初始差為1之外,有效位還差了4/3中低位的位置值,盡管該差可能在任一方向上。
  • 通過Sterbenz'Lemma,從7/3中減去4/3不會有浮點誤差,因此結果恰好是1加上述差值。
  • 減1會產生該差,該差是4/3低位的位置值,除了它可以為正數或負數之外。

暫無
暫無

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

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