Can';t计算C中pow()函数的计算

Can';t计算C中pow()函数的计算,c,floating-point,pow,math.h,C,Floating Point,Pow,Math.h,今天,我发现了一些奇怪的计算,关于C中的math.h函数的pow(),这是我所不知道的(在SO中也没有发现任何问题) 我试验的代码是: #include <stdio.h> #include <math.h> int main(){ //1st case long long result = pow(2, 63); printf("1st case: %lld\n", result); //2nd case result = p

今天,我发现了一些奇怪的计算,关于C中的
math.h
函数的
pow()
,这是我所不知道的(在SO中也没有发现任何问题)

我试验的代码是:

#include <stdio.h>
#include <math.h>

int main(){
    //1st case
    long long result = pow(2, 63);
    printf("1st case: %lld\n", result);

    //2nd case
    result = pow(2, 64);
    printf("2nd case: %lld\n", result);

    //3rd case
    printf("3rd case: %lld\n", (long long) (pow(2, 64)/12000));

    //4th case
    result = pow(2, 64);
    result = result/12000;
    printf("4th case: %lld\n", result);

    //5th case
    result = pow(2, 64) / 12000;
    printf("5th case: %lld\n", result); 

    return 0;
}
我有几个问题我不清楚。我正在使用CodeBlocks 16.01 IDE和GNU GCC编译器

1。在第一种情况下,输出为,
2^63=9223372036854775807
。为什么会这样?最后一个数字在这里是奇数。它应该是
9223372036854775808

2.在第二种情况下,
2^64=9223372036854775807
,这与之前计算的
2^63
相同(实际上,这对于任何大于63的指数值都是相同的)。是的,我知道
long int
数据类型会发生溢出。但是为什么分配了错误的值呢

3.在第三种情况和第五种情况下(实际上相同),答案是正确的。但在第四种情况下,答案是错误的。根据算术运算,第四种情况下的数学运算应该与其余两种情况相同,但实际上并非如此。那么区别在哪里呢?

这些警告(像
gcc prog.c-Wall-Wextra那样编译)对您来说还不够吗

prog.c: In function 'main':
prog.c:6:24: warning: overflow in conversion from 'double' to 'long long int' changes value from '(double)9.2233720368547758e+18' to '9223372036854775807' [-Woverflow]
     long long result = pow(2, 63);
                        ^~~
prog.c:10:14: warning: overflow in conversion from 'double' to 'long long int' changes value from '(double)1.8446744073709552e+19' to '9223372036854775807' [-Woverflow]
     result = pow(2, 64);
              ^~~
prog.c:17:14: warning: overflow in conversion from 'double' to 'long long int' changes value from '(double)1.8446744073709552e+19' to '9223372036854775807' [-Woverflow]
     result = pow(2, 64);
              ^~~
我的意思是溢出发生,然后舍入发生,这给了您这个输出,因为实际值根本不适合该数据类型。如果它是一个长双精度
,情况就不同了。(不要忘记使用
%Lf
打印)

阅读更多


注:在案例3中,您在转换为
long-long
之前进行除法,因此它使用了浮点数,正如Barmar正确评论的那样。

这些警告(如
gcc prog.c-Wall-Wextra
编译)对您来说还不够吗

prog.c: In function 'main':
prog.c:6:24: warning: overflow in conversion from 'double' to 'long long int' changes value from '(double)9.2233720368547758e+18' to '9223372036854775807' [-Woverflow]
     long long result = pow(2, 63);
                        ^~~
prog.c:10:14: warning: overflow in conversion from 'double' to 'long long int' changes value from '(double)1.8446744073709552e+19' to '9223372036854775807' [-Woverflow]
     result = pow(2, 64);
              ^~~
prog.c:17:14: warning: overflow in conversion from 'double' to 'long long int' changes value from '(double)1.8446744073709552e+19' to '9223372036854775807' [-Woverflow]
     result = pow(2, 64);
              ^~~
我的意思是溢出发生,然后舍入发生,这给了您这个输出,因为实际值根本不适合该数据类型。如果它是一个长双精度,情况就不同了。(不要忘记使用
%Lf
打印)

阅读更多




PS:在案例3中,您在转换为
long-long
之前进行除法,因此它使用了浮点数,正如Barmar正确评论的那样。

答案是……舍入!尝试对变量使用
long double
,这样它就是
long double result
。此外,您使用的数字格式可能需要是
pow(2,63.0)
(pow(2,64.0)/12000.0))
。这可能会解决您的问题。如果有人对重复标记有任何问题,请告诉我。如果有问题,我可以打开它。你好@coderredoc,我是这个问题的执行官,我也通过了重复链接,我没有发现相似之处,至少我的帖子中的第三个问题是唯一的,我想我还需要知道答案。你能再复习一下吗?谢谢。您的第三种情况仍然是四舍五入:您将
pow
的双精度结果除以12000,然后转换为整数。在第四种情况下,首先转换,然后分割。我强烈地感觉到,通过阅读关于这个主题的文章,或者通过使用调试器一步一步地处理代码,你可以了解其中的大部分内容。答案是……四舍五入!尝试对变量使用
long double
,这样它就是
long double result
。此外,您使用的数字格式可能需要是
pow(2,63.0)
(pow(2,64.0)/12000.0))
。这可能会解决您的问题。如果有人对重复标记有任何问题,请告诉我。如果有问题,我可以打开它。你好@coderredoc,我是这个问题的执行官,我也通过了重复链接,我没有发现相似之处,至少我的帖子中的第三个问题是唯一的,我想我还需要知道答案。你能再复习一下吗?谢谢。您的第三种情况仍然是四舍五入:您将
pow
的双精度结果除以12000,然后转换为整数。在第四种情况下,首先转换,然后分割。我强烈认为,通过阅读主题或使用调试器逐步完成代码,您可以了解其中的大部分内容。可能OP忽略了这些警告-+1。实际上,我在那里问了三个问题,我主要关心的是第三个问题。计算步骤是如何完成的,当在同一语句中除以12000时,得到正确的结果,而将它们分开则会产生差异。而且,当除以12000时,大于64的值不会发生溢出。是不是类似于pow()的值被计算到更高的值,在除以12000后,我得到了答案。@RakibulIslam在案例3中,您在转换为
long
之前进行除法,因此它使用的是浮点值,这是正确的。谢谢,现在我明白了。也许OP忽略了这些警告-+1。事实上,我问了三个问题,我主要关心的是第三个问题。计算步骤是如何完成的,当在同一语句中除以12000时,得到正确的结果,而将它们分开则会产生差异。而且,当除以12000时,大于64的值不会发生溢出。是不是有点像pow()的值被计算到更高的值,在除以12000后,我得到了答案。@RakibulIslam在案例3中,你在转换为
long
之前进行除法,所以它使用了浮点值,这是正确的。谢谢,现在我明白了。