我正在调试一些旧的C代码,它有一个定义#define PI 3.14 ......其中......大约有50个其他数字。
这是为什么?我说我可以将数字减少到大约16位小数,但是我的老板对我咆哮说其他数字用于平台独立性和向前兼容性。但是程序会慢下来吗?
答案 0 :(得分:7)
不,这不会减慢程序的速度,除非你运行的是一个令人难以置信的动力不足的1MHz DSP芯片,它必须在软件中进行浮点运算,而不是将其传递给专用的FPU。这意味着使用浮点数据的任何数学运算都比使用整数运算慢得多。
一般来说,如果程序中最耗时的部分快速连续进行大量计算,浮点计算速度特别慢,那么更高的精度只会导致速度减慢。在现代CPU上,通常情况并非如此,可能的例外是某些芯片会导致浮点下溢之类的80个周期停顿。这类问题可能超出了这个问题的范畴。
首先,最好使用PI的通用标准定义,例如C标准标题<math.h>
,其中定义为#define M_PI 3.14159265358979323846
。如果你坚持,你可以继续手动定义它。
此外,C中当前可用的最佳精度相当于大约19位数。
根据维基百科,80位&#34;英特尔&#34; IEEE 754扩展精度 long double,即80位填充到内存中的16个字节,有64个 位尾数,没有隐含位,可以得到19.26十进制数 数字。这是长双倍的几乎通用标准 多年来,但事情已经开始发生变化。
较新的128位四精度格式有112个尾数位加上一个 隐含位,可以得到34个十进制数字。 GCC将此实现为 __float128类型和(如果内存服务)编译器选项 设置长双倍。
就个人而言,如果我被要求使用我们自己的pi定义,我会写这样的东西:
#ifndef M_PI
#define PI 3.14159265358979323846264338327950288419716939937510
#else
#define PI M_PI
#endif
如果最新的C标准支持更宽泛的浮点原语数据类型,那么它几乎可以保证数学库中的常量将被更新以支持它。
<强>参考强>
<https://stackoverflow.com/questions/15659668/more-precise-floating-point-data-types-than-double>
<https://stackoverflow.com/questions/9912151/math-constant-pi-value-in-c>
答案 1 :(得分:4)
宏定义中的位数几乎肯定不会对运行时性能产生任何影响。
宏扩展是文本的。这意味着,如果你有:
#define PI 3.14159... /* 50 digits */
然后,只要您在可以看到该定义的代码中引用PI
,就好像您已写出3.14159...
。
C只有三种浮点类型:float
,double
和long double
。大小和精度是实现定义的,但它们通常是32位,64位,宽度大于64位(long double
的大小通常在系统与系统之间的变化比其他两个大不相同。)< / p>
如果在表达式中使用PI
,它将被评估为某种特定类型的值。事实上,如果文字上没有L
后缀,则其类型为double
。
所以如果你写:
double x = PI / 2.0;
就像你写的那样:
double x = 3.14159... / 2.0;
编译器可能会在编译时评估除法,生成类型为double
的值。文字中的任何额外精度都将被丢弃。
要看到这一点,您可以尝试编写一个使用PI
宏并检查汇编列表的小程序。
例如:
#include <stdio.h>
#define PI 3.141592653589793238462643383279502884198716939937510582097164
int main(void) {
double x = PI;
printf("x = %g\n", x);
}
在我的x86_64系统上,生成的机器代码没有引用完整的精度值。与初始化相对应的指令是:
movabsq $4614256656552045848, %rax
其中4614256656552045848
是一个64位整数,对应于尽可能接近3.141592653589793238462643383279502884198716939937510582097164
的数字的二进制IEEE双精度表示。
我系统上实际存储的浮点值恰好是:
3.1415926535897931159979634685441851615905761718750000000000000000
其中只有大约16位十进制数字。