我有一个包含math.h
的C程序,并使用该标头中的sqrt
函数。非常奇怪的是,当我没有传递-Ofast
标志时,我的代码无法编译。
如果我使用以下代码编译我的代码:
gcc -std=c99 foo.c
要么单独添加-O1
,-O2
或-Os
(那些是大写的O&#)到该命令,我会收到以下错误:
/tmp/ccAcT2Bz.o: In function `sum_of_divisors':
foo.c:(.text+0xb): undefined reference to `sqrt'
collect2: error: ld returned 1 exit status
-O3
提供了类似但更详细的错误(请注意,我不会在sqrt
内致电main
):
/tmp/ccBKvvFS.o: In function `sum_of_divisors':
foo.c:(.text+0x5c): undefined reference to `sqrt'
/tmp/ccBKvvFS.o: In function `main':
foo.c:(.text.startup+0xe5): undefined reference to `sqrt'
foo.c:(.text.startup+0xf3): undefined reference to `sqrt'
collect2: error: ld returned 1 exit status
但是,-Ofast
编译没有错误,程序运行完美。所以,
-Ofast
?答案 0 :(得分:4)
我会根据我提供的评论,将此作为答案。
基本上-ffast-math
允许数学优化'不符合IEEE-754标准。一些示例包括允许浮点运算遵守关联性定律,例如,它们表现得像“真实”一样。数字:(a + b) + c == a + (b + c)
- 这是不一个带有浮点数的正确假设。您可以查看gcc
的手册页,查看-ffast-math
启用的选项。
该选项还允许其他代码生成选项偏离IEEE-754标准。应该引起异常,信号NaN等的操作可能不会受到尊重。评论中的示例是sqrt
;如果我们将负值传递给sqrt
,结果可能不符合IEEE-754标准。试图找到这些不一致的来源远远超过现代处理器的任何好处。现代CPU具有大量的浮点资源,正确性远比任何错位的效率感更重要。
在处理浮点数时,有一些非常实际的例子表明尊重实数的关联属性会导致错误的结果。一个例子是Kahan summation。它依赖于浮点运算的非关联属性。还有其他一些例子,仔细分析数值算法依赖于IEEE-754属性。对于三角形区域,另一个例子是Heron's formula。
数值分析是一个广泛的领域,IEEE-754标准代表了一种非常仔细和充分研究的努力,以标准化浮点运算的特殊行为,以及它们与真实&#真实&#的天真理想的偏离39;数字。它代表了数十年研究和经验(更不用说挫折)在数字密集计算方面的巨大努力。
有些人经常在这个网站上回答浮点问题,而且对这个主题的了解比我更广泛。我只是希望说服你-ffast-math
在很多情况下都是不明智的(通常一个具有更好数值条件的算法是更好的第一步),并引入极难找到的错误来源,结果是通常无法在其他平台上重现。避免像瘟疫一样。
答案 1 :(得分:1)
构建可执行文件时必须链接数学库
因此您需要使用-lm
选项进行编译。