有一段时间,我一直在用科学记数法表示常数中10的大幂,这样我就不必计算零了。
#define DELAY_USEC 1e6
一位同事指出,这是不安全的,因为它不是整数,而且不能保证总是等于1000000 exactly。文档似乎证实了这一点,但我想知道它在实践中是否正确。有没有什么方法可以安全地使用速记声明10的幂整数?在define中将其转换为int是否安全?
xn1cxnb41#
从理论上讲,没有。这两种语言都没有指定如何表示浮点值,也没有指定哪些值可以精确表示。(更新:显然,C11确实推荐了一种表示法。C++和更老的C方言则不推荐。实际上,是的,对于相当大范围的值。任何你可能遇到的实现都将使用64-bit IEEE representation来表示double。这可以精确地表示任何整数值,直到253(大约9x1015)。它当然可以表示任何可以用32位整数类型表示的值。
double
k0pti3hp2#
要使用user-defined literals:
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;
vmpqdwk33#
如果你问的是10的幂,1e6正好是100万。你可以一直查到1e22而不会发生任何问题。但是,请注意,在C++和C中,1e6都是double常量,而不是整型常量。10的负幂则是另一回事。1e-1是不精确的,所有较低的幂也是如此。
1e6
1e22
1e-1
uurity8g4#
看起来gcc假定一个使用科学记数法定义的常量为浮点数,除非它是强制转换的。一个简单的C代码显示了这一点:
gcc
#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):
$ 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所述,10 e15和10 e22是10的最大幂数,它们分别以简单和双精度浮点格式精确表示。无法使用32位或64位整数类型表示更大的10的幂。
mwkjh3gx5#
对于小于INT_MAX的值,永远不会出现舍入误差,因为double的规范将52 bits for you to use排除在外。“小数部分”只是整数,“指数”将是1,浮点不受此影响。
INT_MAX
lhcgjxsq6#
这真的不安全,因为编译器会将其视为浮点数,因此精度限制为53位,而不是64位整数(长整型)。http://en.wikipedia.org/wiki/Floating_point
6条答案
按热度按时间xn1cxnb41#
从理论上讲,没有。这两种语言都没有指定如何表示浮点值,也没有指定哪些值可以精确表示。(更新:显然,C11确实推荐了一种表示法。C++和更老的C方言则不推荐。
实际上,是的,对于相当大范围的值。任何你可能遇到的实现都将使用64-bit IEEE representation来表示
double
。这可以精确地表示任何整数值,直到253(大约9x1015)。它当然可以表示任何可以用32位整数类型表示的值。k0pti3hp2#
要使用user-defined literals:
那么您可以简单地执行以下操作:
vmpqdwk33#
如果你问的是10的幂,
1e6
正好是100万。你可以一直查到1e22
而不会发生任何问题。但是,请注意,在C++和C中,1e6
都是double
常量,而不是整型常量。10的负幂则是另一回事。
1e-1
是不精确的,所有较低的幂也是如此。uurity8g4#
看起来
gcc
假定一个使用科学记数法定义的常量为浮点数,除非它是强制转换的。一个简单的C代码显示了这一点:
在x86-64计算机上,
gcc
生成以下汇编代码($ gcc -S define.c
):如here所述,10 e15和10 e22是10的最大幂数,它们分别以简单和双精度浮点格式精确表示。
无法使用32位或64位整数类型表示更大的10的幂。
mwkjh3gx5#
对于小于
INT_MAX
的值,永远不会出现舍入误差,因为double
的规范将52 bits for you to use排除在外。“小数部分”只是整数,“指数”将是1,浮点不受此影响。lhcgjxsq6#
这真的不安全,因为编译器会将其视为浮点数,因此精度限制为53位,而不是64位整数(长整型)。
http://en.wikipedia.org/wiki/Floating_point