C: ошибочный вывод для "(long long int) = (long long int) * (double)"? - PullRequest
0 голосов
/ 12 сентября 2009
long long int A = 3289168178315264;
long long int B = 1470960727228416;
double D = sqrt(5);

long long int out = A + B*D;

printf("%lld",out);

Это дает результат: -2147483648

Я не могу понять, почему (это должен быть положительный результат). Может ли кто-нибудь помочь?

Ответы [ 5 ]

3 голосов
/ 12 сентября 2009

может быть, вы должны указать эти константы как "длинные длинные" литералы? например 3289168178315264LL

1 голос
/ 12 сентября 2009

Какой компилятор / операционную систему вы используете? Я запустил ваш код, используя Visual C ++ 2008 Express Edition для Windows XP, и ЭТО РАБОТАЕТ - ответ: 6578336356630528 (это 53-разрядное число, поэтому оно просто помещается в двойное число).

Я также попробовал два варианта, чтобы определить, имеет ли значение порядок операций:

long long int out = A; из + = B * D *; 1005 *

long long int out = B * D; выход + = А;

Они оба тоже работают!

Любопытный.

0 голосов
/ 12 сентября 2009

Ваш ответ (должен подтвердить) рассчитывается успешно, однако он вызывает переполнение в знаковый бит, что делает ответ отрицательным. Решение: сделайте все ваши переменные без знака.

Почему:

Числа хранятся в виде последовательности битов в памяти вашего компьютера. Первый бит в такой серии при установке означает, что ваш номер отрицателен. Таким образом, расчет работает, но переходит в знаковый бит.

Рекомендация:

Если вы работаете с такими большими числами, я рекомендую вам получить библиотеку арифметических вычислений. «Это сэкономит вам много времени и хлопот».

0 голосов
/ 12 сентября 2009

Я предполагаю, что компилятору сначала нужно округлить результат от "A + B * D" до целого числа, потому что вы сохраняете результат в поле int. В общем, у вас конфликт типов данных.

И A, и B по-прежнему являются действительными числами для long long int, длина которого составляет 8 байтов. Вы можете даже умножить их на 1.000 и при этом иметь действительные значения long long int. В некоторых других языках он также известен как int64.

Однако значение типа double также 64-битное, но часть из них используется как показатель степени. Когда вы умножаете double на int64, результатом будет еще один double. Добавление другого int64 к нему все еще сохраняет его двойным. Затем вы снова присваиваете результат для int64 без использования определенного метода округления. Меня не удивит, если для этого компилятор будет использовать 4-битную функцию округления. Я даже поражен, что компилятор не вырвет и не нарушит это утверждение!

В любом случае, при использовании таких больших чисел необходимо соблюдать особую осторожность при смешивании разных типов.

0 голосов
/ 12 сентября 2009

Параметр в sqrt должен быть double .

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

А также мы должны объяснить приведение результата из 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);
...