简体   繁体   English

C:“(long long int)=(long long int)*(double)”的输出错误?

[英]C : erroneous output for “(long long int) = (long long int) * (double)”?

long long int A = 3289168178315264;
long long int B = 1470960727228416;
double D = sqrt(5);

long long int out = A + B*D;

printf("%lld",out);

This gives result : -2147483648 得到的结果是:-2147483648

I am not able to figure out why (it should be a positive result). 我无法弄清楚原因(应该是积极的结果)。 Can somebody help? 有人可以帮忙吗?

maybe you have to specify those constants as "long long" literals? 也许您必须将这些常量指定为“ long long long”字面量? eg 3289168178315264LL 例如3289168178315264LL

What compiler/operating system are you using? 您正在使用什么编译器/操作系统? I ran your code using Visual C++ 2008 Express Edition on Windows XP and IT WORKS - answer: 6578336356630528 (this is a 53-bit number, so it just fits inside a double). 我在Windows XP和IT WORKS上使用Visual C ++ 2008 Express Edition运行了您的代码-答案:6578336356630528(这是一个53位数字,因此只适合一个双精度数)。

I also tried two variations to see if the order of operations mattered: 我还尝试了两种变体来查看操作顺序是否重要:

long long int out = A; long long int out = A; out+=B*D; out + = B * D;

long long int out = B*D; long long int输出= B * D; out+=A; out + = A;

These both work as well! 这些都工作!

Curious. 好奇。

My guess is that the compiler needs to round the result from "A+B*D" to an integer first, because you're storing the result inside an int field. 我的猜测是,编译器需要首先将结果从“ A + B * D”四舍五入为整数,因为您将结果存储在int字段中。 So basically, you're having a datatype conflict. 因此,基本上,您遇到了数据类型冲突。

Both A and B are still valid numbers for a long long int, which is 8 bytes long. 对于长long int(8字节长),A和B仍然是有效数字。 You could even multiply them by 1.000 and still have valid long long int values. 您甚至可以将它们乘以1.000,但仍然具有有效的long long int值。 In some other languages it's also known as the int64. 在其他一些语言中,它也称为int64。

A double, however, is also 64-bits but part of those are used as exponent. 但是,double也是64位,但其中一部分用作指数。 When you multiply a double with an int64, the result would be another double. 当您将一个double与int64相乘时,结果将是另一个double。 Adding another int64 to it still keeps it a double. 向其添加另一个int64仍使其保持两倍。 Then you're assigning the result to an int64 again without using a specific rounding method. 然后,您无需使用特定的舍入方法即可将结果再次分配给int64。 It would not surprise me if the compiler would use a 4-bit rounding function for this. 如果编译器为此使用4位舍入函数,这也不会令我感到惊讶。 Am even amazed that the compiler doesn't puke and break on that statement! 我什至惊讶编译器不会吐槽并破坏该语句!

Anyways, when using large numbers like these, you have to be extra careful when mixing different types. 无论如何,当使用这样的大量数字时,混合不同类型的数字时必须格外小心。

Your answer (have to verify) calcuates successfully, however, it causes an overflow into the sign bit, which makes the answer negative. 您的答案(必须验证)计算成功,但是,它导致符号位溢出,从而使答案是否定的。 Solution : make all your variables unsigned. 解决方案:使所有变量均无符号。

Why: 为什么:

Numbers are stored as series of bits in you computer's memory. 数字以位序列的形式存储在计算机的内存中。 The first bit in such a series, when set means that you number is negative. 设置为此类系列的第一位时,表示您的数字为负。 So the calculation works, but overflows into the sign bit. 因此计算有效,但溢出到符号位中。

Recommendation: 建议:

If you're working with numbers this big, I recommend you to get a multiprecision arithmetic library. 如果要处理这么大的数字,我建议您获取一个多精度算术库。 'T will save you a lot of time and trouble. 'T将为您节省很多时间和麻烦。

The parameter to sqrt should be double . sqrt的参数应为double

#include <math.h>
double sqrt( double num );

And also we should explict cast the result from B * D to long long. 并且我们还应该将结果从B * D强制转换为long long。

    long long int A = 3289168178315264;
    long long int B = 1470960727228416;
    double D = sqrt(5.0);
    printf("%f\n",D);
    long long int out = A + (long long) (B * D);
    printf("%lld",out);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM