计算函数并检查其域

我的任务是计算以下function:

∛日志5 (x 2 – √x)

对于论证x = [-5; 10],增量为0.2。 所以为了让x满足函数的域,我想我们必须针对2种情况进行测试:

double myPow(double x, double y) { if (x < 0.0) return -pow(-x, y); else return pow(x, y); } //... for(double x = -5.0 ; x = 0.0 && (pow(x, 2.0) - sqrt(x)) > 0.0) { //myPow correctly calculates the cube root if x < 0 (see def. of std. pow) double sum = myPow(log(pow(x, 2.0) - sqrt(x))/log(5), 1/3.0); printf("%f ", sum); } //... } 

但是,当x == 1.0时,第二个条件应该等于:

 pow(1.0, 2.0) - sqrt(1.0) == 0.0 

它确实如此,当我按照上面的方式单独编写它时,但是在我的for循环中它没有 – 它等于类似的东西:0.00000000000000310862 …

为什么会发生这种情况,如何纠正它以不通过if条件(从而满足对数约束)?

double x = 0.2并不完全是1/5,它正好是0.200000000000000011102230246251565404236316680908203125

因此,当您重复添加此数字时,您会累积小的舍入错误。

假设有一个严格的IEEE 754双精度运算应用(没有中间额外的精度),你的循环将提供那些双精度(我使用最小的十进制表示,如果正确舍入到最近的偶数,将舍入到相同的双精度):

-5.0 -4.8 -4.6 -4.3999999999999995 -4.199999999999999 -3.999999999999999 -3.799999999999999 -3.5999999999999988 -3.3999999999999986 -3.1999999999999984 -2.9999999999999982 -2.799999999999998 -2.599999999999998 -2.3999999999999977 -2.1999999999999975 -1.9999999999999976 -1.7999999999999976 -1.5999999999999976 -1.3999999999999977 -1.1999999999999977 -0.9999999999999978 -0.7999999999999978 -0.5999999999999979 -0.39999999999999786 -0.19999999999999785 2.1649348980190553e-15 0.20000000000000218 0.4000000000000022 0.6000000000000022 0.8000000000000023 1.0000000000000022 1.2000000000000022 1.4000000000000021 1.600000000000002 1.800000000000002 2.000000000000002 2.2000000000000024 2.4000000000000026 2.6000000000000028 2.800000000000003 3.000000000000003 3.2000000000000033 3.4000000000000035 3.6000000000000036 3.800000000000004 4.0000000000000036 4.200000000000004 4.400000000000004 4.600000000000004 4.800000000000004 5.000000000000004 5.200000000000005 5.400000000000005 5.600000000000005 5.8000 00000000005 6.000000000000005 6.2000000000000055 6.400000000000006 6.600000000000006 6.800000000000006 7.000000000000006 7.200000000000006 7.400000000000007 7.600000000000007 7.800000000000007 8.000000000000007 8.200000000000006 8.400000000000006 8.600000000000005 8.800000000000004 9.000000000000004 9.200000000000003 9.400000000000002 9.600000000000001 9.8 10.0

您可以通过使用来改进

 for(int i=-25; i<=50; ++i) { double x = i * 0.2; 

但它并不完美,0.2并没有完全按照我们上面的说法表示,你得到:

-5.0 -4.800000000000001 -4.6000000000000005 -4.4 -4.2 -4.0 -3.8000000000000003 -3.6 -3.4000000000000004 -3.2 -3.0 -2.8000000000000003 -2.6 -2.4000000000000004 -2.2 -2.0 -1.8 -1.6 -1.4000000000000001 -1.2000000000000002 -1.0 -0.8 -0.6000000000000001 -0.4 -0.2 0.0 0.2 0.4 0.6000000000000001 0.8 1.0 1.2000000000000002 1.4000000000000001 1.6 1.8 2.0 2.2 2.4000000000000004 2.6 2.8000000000000003 3.0 3.2000000000000004 3.6 3.8000000000000003 4.0 4.2 4.4 4.6000000000000005 4.800000000000001 5.0 5.2 5.4 5.6000000000000005 5.800000000000001 6.0 7.2 6.4 6.6000000000000005 6.800000000000001 7.0 7.2 7.4 7.6000000000000005 7.800000000000001 8.0 8.200000000000001 8.4 8.6 8.8 9.0 9.200000000000001 9.4 9.600000000000001 9.8 10.0

如果你试试

 for(int i=-25; i<=50; ++i) { double x = i / 5.0; 

这是你用浮点数得到的最好的,因为你得到的最近浮点近似为1/5的倍数:

-5.0 -4.8 -4.6 -4.4 -4.2 -4.0 -3.8 -3.6 -3.4 -3.2 -3.0 -2.8 -2.6 -2.4 -2.2 -2.0 -1.8 -1.6 -1.4 -1.2 -1.0 -0.8 -0.6 -0.4 -0.2 0.0 0.2 0.4 0.6 0.8 1.0 1.2 1.4 1.6 1.8 2.0 2.2 2.4 2.6 2.8 3.0 3.2 3.4 3.6 3.8 4.0 4.2 4.4 4.6 4.8 5.0 5.2 5.4 5.6 5.8 6.0 6.2 6.4 6.8 7.0 7.2 7.4 7.6 7.8 8.0 8.2 8.4 8.6 8.8 9.0 9.2 9.4 9.6 9.8 10.0