C++ 模数返回错误答案
C++ Modulus returning wrong answer
这是我的代码:
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
int n, i, num, m, k = 0;
cout << "Enter a number :\n";
cin >> num;
n = log10(num);
while (n > 0) {
i = pow(10, n);
m = num / i;
k = k + pow(m, 3);
num = num % i;
--n;
cout << m << endl;
cout << num << endl;
}
k = k + pow(num, 3);
return 0;
}
当我输入 111
它给了我这个
1
12
1
2
我正在使用代码块。不知道怎么回事。
每当我使用 pow 期望整数结果时,我都会添加 .5,所以我使用 (int)(pow(10,m)+.5)
而不是让编译器自动将 pow(10,m)
转换为 int。
我读过很多地方,告诉我其他人已经对我添加 .5
的某些情况进行了详尽的测试,发现它产生影响的情况为零。但准确识别不需要它的条件可能非常困难。在不需要时使用它并没有真正的危害。
如果它有所作为,那就是您想要的不同。如果它没有什么不同,它的成本很小。
在发布的代码中,我会以这种方式调整对 pow
的每个调用,而不仅仅是我用作示例的调用。
没有针对您使用 log10
的同样简单的修复,但它可能会遇到同样的问题。由于您期望得到一个非整数答案,并且希望 将该非整数答案截断为一个整数,因此添加 .5 将是非常错误的。因此,您可能需要找到一些更复杂的解决方法来解决使用浮点数的基本问题。我不确定,但假设是 32 位整数,我认为在转换为 int
之前将 1e-10
添加到 log10
的结果中都不足以将 log10(10^n-1)
更改为log10(10^n)
但总是足以纠正可能造成相反结果的错误。
pow
进行 浮点运算 求幂。
浮点函数和运算是不精确的,你不能永远依赖它们来给你精确的值计算,除非您精通 IEEE 浮点表示的详细信息以及您的库函数提供的保证。
(而且,浮点数甚至可能无法准确表示您想要的整数)
当您将结果转换为整数时,这尤其有问题,因为结果被截断为零:int x = 0.999999;
设置 x == 0
,而不是 x == 1
。即使是在错误方向上的最小错误也会完全破坏结果。
您可以四舍五入到最接近的整数,但这也有问题;例如如果数字足够大,您的浮点数可能没有足够的精度来接近您想要的结果。或者,如果您对浮点数进行了足够多的操作(或不稳定的操作),错误可能会累积到您得到错误的最接近整数的程度。
如果您想进行精确的整数运算,那么您应该使用这样做的函数。例如编写您自己的 ipow
函数,无需任何浮点运算即可计算整数幂。
这是我的代码:
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
int n, i, num, m, k = 0;
cout << "Enter a number :\n";
cin >> num;
n = log10(num);
while (n > 0) {
i = pow(10, n);
m = num / i;
k = k + pow(m, 3);
num = num % i;
--n;
cout << m << endl;
cout << num << endl;
}
k = k + pow(num, 3);
return 0;
}
当我输入 111
它给了我这个
1
12
1
2
我正在使用代码块。不知道怎么回事。
每当我使用 pow 期望整数结果时,我都会添加 .5,所以我使用 (int)(pow(10,m)+.5)
而不是让编译器自动将 pow(10,m)
转换为 int。
我读过很多地方,告诉我其他人已经对我添加 .5
的某些情况进行了详尽的测试,发现它产生影响的情况为零。但准确识别不需要它的条件可能非常困难。在不需要时使用它并没有真正的危害。
如果它有所作为,那就是您想要的不同。如果它没有什么不同,它的成本很小。
在发布的代码中,我会以这种方式调整对 pow
的每个调用,而不仅仅是我用作示例的调用。
没有针对您使用 log10
的同样简单的修复,但它可能会遇到同样的问题。由于您期望得到一个非整数答案,并且希望 将该非整数答案截断为一个整数,因此添加 .5 将是非常错误的。因此,您可能需要找到一些更复杂的解决方法来解决使用浮点数的基本问题。我不确定,但假设是 32 位整数,我认为在转换为 int
之前将 1e-10
添加到 log10
的结果中都不足以将 log10(10^n-1)
更改为log10(10^n)
但总是足以纠正可能造成相反结果的错误。
pow
进行 浮点运算 求幂。
浮点函数和运算是不精确的,你不能永远依赖它们来给你精确的值计算,除非您精通 IEEE 浮点表示的详细信息以及您的库函数提供的保证。
(而且,浮点数甚至可能无法准确表示您想要的整数)
当您将结果转换为整数时,这尤其有问题,因为结果被截断为零:int x = 0.999999;
设置 x == 0
,而不是 x == 1
。即使是在错误方向上的最小错误也会完全破坏结果。
您可以四舍五入到最接近的整数,但这也有问题;例如如果数字足够大,您的浮点数可能没有足够的精度来接近您想要的结果。或者,如果您对浮点数进行了足够多的操作(或不稳定的操作),错误可能会累积到您得到错误的最接近整数的程度。
如果您想进行精确的整数运算,那么您应该使用这样做的函数。例如编写您自己的 ipow
函数,无需任何浮点运算即可计算整数幂。