pow() 函数在括号中使用时出现奇怪的行为并且带有 long long integer

pow() function weird behavior when used in brackets and with long long integer

我发现了一些奇怪的东西。

此函数将数字放入给定位置的数字中,并 returns 修改后的数字。 现在我们想做 put_digit(123456789123456784, 0, 9); 这会将 9 放在数字的末尾,替换最后一个数字 (4)。

这是有效的代码:

long long int put_digit(long long int number, char place, char digit)
{
    long long int result = number;
    long long int power = number;

    power = pow(10, (place));
    result -= get_digit(number, place)*power;
    result += digit*pow(10, (place));

    return result;
}

代码returns123456789123456789

这是行不通的代码:

long long int put_digit(long long int number, char place, char digit)
{
    long long int result = number;

    result -= get_digit(number, place)*pow(10, (place));
    result += digit*pow(10, (place));

    return result;
}

此代码 returns 123456789123456800 作为结果。

函数 get_digit() returns 从给定位置的数字中提取数字。 这是它的代码:

char get_digit(long long int number, char place)
{
    long long int target = number;
    char digit = 0;

    target /= pow(10, place);
    digit = target % 10;

    return digit;
}

• 较小的数字不会发生这种情况。

• get_digit() 总是 returns 正确的值(在本例中为 4)。

• get_digit() 是一个 char,因为这不是计数器函数,因此最好专注于使用更少的内存,而不是使用像 int 这样更快的变量。

• 我曾尝试使用括号来避免麻烦的运算符优先级,但无济于事。

• 在执行 put_digit(123456789123456000, 2, 7) 时也观察到奇怪的行为,由于某种原因 returns 123456789123456704。这通过替换第二个结果中的 pow 函数来解决用变量 "power".

计算

我只是不明白为什么会这样。

我是不是有点溢出了?是我系统的问题还是我自己的问题?我使用 pow() 的方式不好吗?

pow()的声明是:double pow( double base, double exponent );

第一种情况:

long long int power = number;

power = pow(10, (place));

pow()返回的值在赋值power时被转换为long long int。其余的计算使用整数进行处理,结果就是您所期望的。

关于第二种情况:

result -= get_digit(number, place)*pow(10, (place));

get_digit(number, place)返回的值被转换为double,因为它需要乘以一个浮点数(pow()返回)。此外,在减去乘法结果之前,result 的值被转换为 double。最后,将计算值从double转换为long long int存储在result.

但是从某个量级开始,浮点数会失去其最低有效数字的精度。

自己试试这段简单的代码:

long long int i = 123456789123456785;

for (; i <= 123456789123456795; i ++) {
  printf("long long int: %lld; double: %f\n", i, (double)i);
}

它输出:

long long int: 123456789123456785; double: 123456789123456784.000000
long long int: 123456789123456786; double: 123456789123456784.000000
long long int: 123456789123456787; double: 123456789123456784.000000
long long int: 123456789123456788; double: 123456789123456784.000000
long long int: 123456789123456789; double: 123456789123456784.000000
long long int: 123456789123456790; double: 123456789123456784.000000
long long int: 123456789123456791; double: 123456789123456784.000000
long long int: 123456789123456792; double: 123456789123456800.000000
long long int: 123456789123456793; double: 123456789123456800.000000
long long int: 123456789123456794; double: 123456789123456800.000000
long long int: 123456789123456795; double: 123456789123456800.000000

此行为不是错误,而是浮点数的限制。

您的代码的解决方案是将 pow(10, place) 返回的值尽快转换为 long long int returns:

result -= get_digit(number, place)*(long long int)pow(10, place);