有一段时间,我使用科学记数法代表常数中的10大常数,因此我不必计算零。 e.g。
#define DELAY_USEC 1e6
一位同事指出,这不安全,因为它不是一个整数,并且不能保证总是等于1000000 正好。文档似乎证实了这一点,但我想知道它在实用性方面是否真实。有没有办法用速记安全地声明十次幂的整数?将它强制转换为定义中的int是否安全?
答案 0 :(得分:21)
理论上,没有。两种语言都没有指定如何表示浮点值,或者哪些值可以精确表示。 (更新:显然,C11确实推荐了一种表示法.C ++和旧的C语言,不要)。
在实践中,是的,适用于很大范围的值。您可能遇到的任何实施都会使用double
{{1}}。这可以精确地表示高达2 53 (大约9x10 15 )的任何整数值。它当然可以代表32位整数类型所代表的任何东西。
答案 1 :(得分:8)
您想要使用用户定义的文字:
constexpr long long operator "" _k(long long l) {
return l * 1000;
}
constexpr long long operator "" _m(long long l) {
return l * 1000 * 1000;
}
然后你可以简单地做:
long long delay = 1_m;
long long wait = 45_k;
答案 2 :(得分:8)
你具体询问十的权力。 1e6
将是一百万。您可以前往1e22
而不会发生任何不良事件。但请注意,在C ++和C中,1e6
是double
常量,而不是整数常量。
十的负面力量是另一回事。 1e-1
与所有较低权力一样不精确。
答案 3 :(得分:2)
似乎gcc
假定使用科学记数法将常量定义为浮点数,除非它是强制转换的。
一个简单的C代码显示了这一点:
#include <stdio.h>
#define DELAY_USEC_FP 1e6
#define DELAY_USEC_INT (unsigned int) 1e6
int main()
{
printf("DELAY_USEC_FP: %f\n", DELAY_USEC_FP);
printf("DELAY_USEC_INT: %u\n", DELAY_USEC_INT);
return 0;
}
在x86-64计算机上,gcc
生成此汇编代码($ gcc -S define.c
):
[...]
; 0x4696837146684686336 = 1e6 in double-precision FP IEEE-754 format
movabsq $4696837146684686336, %rax
[...]
call printf
movl $1000000, %esi
[...]
call printf
movl $0, %eax
如上所述here,10e15和10e22分别是10个数字的最大幂,它们分别以简单和双精度浮点格式具有精确表示。
使用32位或64位整数类型无法表示10个数字的更大功率。
答案 4 :(得分:0)
由于INT_MAX
的规范预留了52 bits for you to use,因此您永远不会在double
以下的内容上出现舍入错误。你的“小数分量”只是你的整数,你的“指数”将是1,浮点数不会与之相悖。
答案 5 :(得分:0)
这真的不安全,因为编译器会将其视为浮点数,因此精度限制为53位而不是64位整数(long int),您可以阅读更多关于浮点数numbrers的表示< / p>