简体   繁体   English

对于C中的整数常量,科学记数法是否安全?

[英]Is scientific notation safe for integer constants in C?

For a while, I've been representing large powers of 10 in constants using scientific notation, just so I don't have to count the zeros. 有一段时间,我一直用科学记数法表示常量中10的大功率,所以我不必算零。 eg 例如

#define DELAY_USEC 1e6

A colleague pointed out that this isn't safe, because it's not an integer and is not guaranteed to always equal 1000000 exactly . 一位同事指出这不安全,因为它不是一个整数,并不能保证总是完全等于1000000。 Documentation seems to confirm this, but I'm wondering if its true in practicality. 文档似乎证实了这一点,但我想知道它的实用性是否真实。 Is there any way to safely declare a power-of-ten integer using a shorthand? 有没有办法用速记安全地声明十次幂的整数? Is it safe just to cast it to an int in the define? 将它强制转换为定义中的int是否安全?

In theory, no. 从理论上讲,没有。 Neither language specifies how floating point values are represented, or which values can be represented exactly. 两种语言都没有指定如何表示浮点值,或者哪些值可以精确表示。 (UPDATE: apparently, C11 does recommend a representation. C++, and older C dialects, don't). (更新:显然,C11确实推荐一种表示法.C ++和旧的C方言,不要)。

In practice, yes, for quite a large range of values. 在实践中,是的,对于相当大的价值范围。 Any implementation you're remotely likely to encounter will use a 64-bit IEEE representation for double . 您可能遇到的任何实现都将使用64位IEEE表示形式进行double This can represent any integer value up to 2 53 (approximately 9x10 15 ) exactly. 这可以精确地表示高达2 53 (大约9x10 15 )的任何整数值。 It can certainly represent anything representable by a 32-bit integer type. 它当然可以代表32位整数类型所代表的任何东西。

You want to use 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;
}

then you can simple do: 然后你可以简单地做:

long long delay = 1_m;
long long wait = 45_k;

You ask specifically about powers of ten. 你具体问十个权力。 1e6 will be exactly one million. 1e6将是一百万。 You can go up to 1e22 without anything bad happening. 你可以在没有发生任何不良事件的情况下升至1e22 However, note that in both C++ and C, 1e6 is a double constant, rather than an integer constant. 但是,请注意,在C ++和C中, 1e6double常量,而不是整数常量。

Negative powers of ten are a different story. 十个负面的力量是一个不同的故事。 1e-1 is inexact, as are all lower powers. 1e-1是不精确的,所有低权力也是如此。

It seems that gcc assumes a constant defined using scientific notation as a floating point number unless it is cast. 似乎gcc假定使用科学记数法定义的常量作为浮点数,除非它是强制转换的。

A simple C code shows this: 一个简单的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;
}

On a x86-64 machine, gcc generates this assembly code ( $ gcc -S define.c ): 在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

As stated here , 10e15 and 10e22 are the maximum power of ten numbers that have an exact representation in simple and double-precision floating-point format, respectively. 如前所述这里 ,10E15和10e22是具有简单和双精度浮点数的确切表示,分别为10个数字的最大功率。

Larger power of ten numbers can not be represented using 32-bit or 64-bit integer types. 使用32位或64位整数类型无法表示10个数字的更大功率。

You'll never get rounding errors on something less than INT_MAX , since the specification for double sets aside 52 bits for you to use . 你永远不会在小于INT_MAX东西上得到舍入错误,因为double的规范设置了52位供你使用 Your "fractional component" is just your integer, and your "exponent" will be 1, and floating point doesn't struggle with that. 你的“小数分量”只是你的整数,你的“指数”将是1,浮点数不会那么挣扎。

It's really not safe because the compiler will consider it as a floating point number, so the precision is limited to 53 bits instead of 64 bits of integers (long int) for more you can read about the presentation of floating point numbrers 这真的不安全,因为编译器会将其视为浮点数,因此精度限制为53位而不是64位整数(long int),您可以阅读更多关于浮点数numbrers的表示

http://en.wikipedia.org/wiki/Floating_point http://en.wikipedia.org/wiki/Floating_point

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM