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);
我发现了一些奇怪的东西。
此函数将数字放入给定位置的数字中,并 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);