Is scientific notation safe for integer constants in C?

前端 未结 6 737
心在旅途
心在旅途 2021-02-03 18:04

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. e.g.

#define DELAY_USE         


        
相关标签:
6条回答
  • 2021-02-03 18:35

    You ask specifically about powers of ten. 1e6 will be exactly one million. You can go up to 1e22 without anything bad happening. However, note that in both C++ and C, 1e6 is a double constant, rather than an integer constant.

    Negative powers of ten are a different story. 1e-1 is inexact, as are all lower powers.

    0 讨论(0)
  • 2021-02-03 18:38

    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;
    
    0 讨论(0)
  • 2021-02-03 18:38

    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. Your "fractional component" is just your integer, and your "exponent" will be 1, and floating point doesn't struggle with that.

    0 讨论(0)
  • 2021-02-03 18:43

    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).

    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. This can represent any integer value up to 253 (approximately 9x1015) exactly. It can certainly represent anything representable by a 32-bit integer type.

    0 讨论(0)
  • 2021-02-03 18:43

    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

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

    0 讨论(0)
  • 2021-02-03 19:01

    It seems that gcc assumes a constant defined using scientific notation as a floating point number unless it is cast.

    A simple C code shows this:

    #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):

    [...]
    ; 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.

    Larger power of ten numbers can not be represented using 32-bit or 64-bit integer types.

    0 讨论(0)
提交回复
热议问题