1

我尝试了以下方法,似乎“测试”导致错误值。2500*2500*2500 == 15625000000,为什么下面的操作会导致不同的结果?

unsigned long long int test = 2500*2500*2500;
fprintf(stderr, "*************** test = %lld, %llu\n", test, test);
unsigned long long int test2 = 15625000000;
fprintf(stderr, "*************** test2 = %lld, %llu\n", test2, test2);

结果:

*************** test = -1554869184, 18446744072154682432
*************** test2 = 15625000000, 15625000000
4

2 回答 2

3

2500 * 2500 * 2500永远不会提升到过去int,因此发生的有符号溢出(顺便说一下,UB)会阻止执行正确的计算。

要允许它,您必须告诉编译器您的文字属于特定类型。有两种方法可以做到这一点:

  1. 通过强制转换- 转换文字通常在编译时处理并且没有运行时开销:

    unsigned long long int test = (unsigned long long int)2500 * (unsigned long long int)2500 * (unsigned long long int)2500;
    

    请注意,强制转换是在被乘数上单独执行的。如果操作的结果被强制转换(例如(unsigned long long int)(2500 * 2500 * 2500)),那么强制转换将太晚而无法保存数据。

  2. 通过后缀

    unsigned long long int test = 2500ULL * 2500ULL * 2500ULL;
    

    这在运行时与文字转换一样有效,但根据使用情况可能更容易或更难阅读。后缀必须直接应用于文字(不能应用于运算结果,因此 (2500 * 2500 * 2500)ULL是非法的。)

于 2012-07-02T05:32:52.713 回答
2

2500*2500*2500不是 unsigned long long 只是因为您将它复制到 unsigned long long。乘法是用ints 完成的,所以乘法的结果是int。当升级unsigned long long发生时,为时已晚。使用2500ULL.

于 2012-07-02T05:32:10.773 回答