2016-07-28 2 views
-4

Я писал небольшой алгоритм с наименьшим общим множественным числом и столкнулся с чем-то, чего не понимаю. Это первая и последняя часть кода:Неверный порядок операций? (C++)

long a = 14159572; 
long b = 63967072; 
int rest = 4; 
long long ans; 
. 
. // Some other code here that is not very interesting. 
. 
    else 
{ 
    //This appears correct, prints out correct answer. 

    ans = b/rest; 
    std::cout << a*ans; 
} 

Но если я изменю последний «еще» на это дает ответ, что гораздо меньше, и неправильно:

else 
{ 

    std::cout << a*(b/rest); 
} 

Кто-нибудь знает, почему это? Я не думаю, что это переполнение, потому что это не отрицательное число, которое получилось неправильным, а скорее намного меньшим целым числом (около 6 * 10^8), чем фактический ответ (около 2.2 * 10^14). Насколько я понимаю, он должен сначала рассчитать «b/rest» в обоих случаях, поэтому ответы не должны отличаться?

+0

Вы пропустили, чтобы предоставить реальный код, который вы написали – Dutow

+0

Я считаю, что компилятор читает слева направо. Таким образом, он может распространять «а» через паренс и давать немного другой ответ. – Winter

+3

Тип 'a * ans'' long long ', но тип 'a * (b/rest)' просто 'long'. – user975989

ответ

2

разница не порядок операций, но типы данных:

ans = b/rest; // b/rest is long which upscaled to long long 
std::cout << a*ans; // a converted to long long and result is long long 

против:

std::cout << a*(b/rest); // a*(b/rest) all calculations in long 

так что если вы измените свой второй вариант:

std::cout << a*static_cast<long long>(b/rest); 

вы должны увидеть такой же результат.

Update, почему ваш бросок не работает, обратите внимание на разницу:

long a,b; 
// divide `long` by `long` and upscale result to `long long` 
std::cout << static_cast<long long>(a/b); 
// upscale both arguments to `long long` and divide `long long` by `long long` 
std::cout << a/static_cast<long long>(b); 
+0

Было бы лучше просто использовать 'int64_t'? –

+0

Этот вопрос для OP, а не для меня – Slava

+0

Спасибо! Некоторое время искал пример того, как были преобразованы типы данных, я подозревал, что проблема - это нечто подобное. Я попытался сделать следующее, прежде чем это не сработало: 'std :: cout << long long (a * (b/rest))' Но я думаю, что это не правильный способ сделать его длинным long ... –

2

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

В вашем случае конкретно long почти наверняка представляет собой 32-разрядное целое число, а не long long, что, вероятно, является 64-разрядным целым числом.

Поскольку максимальное значение 32-разрядного знакового целого составляет примерно 2 миллиарда, 14159572 * (63967072/4) наиболее определенно переполняет диапазон.

Удостоверьтесь, что выполняете свои расчеты с использованием номеров long long, или же пересматривайте свой код, чтобы избежать переполнения в первую очередь.

+1

Вы имеете в виду 'byte', а не' bit'. –

+0

@JesperJuhl Я на самом деле имел в виду «32-битные» и «64-битные» целые числа, но хороший улов! – Xirema

+0

Спасибо :) Я все еще очень новичок в C++ и не знал, как «long longs» 'longs' и' ints' были конвертированы при смешивании. –

0

Компилятор принимает типы данных для каждого операнда вашего математического уравнения и выполняет умножение и деление в соответствии с предполагаемыми типами данных (см. «Целочисленное деление»). Это также относится к промежуточным вычислениям. Это также относится к результату, переданному потоку, поскольку вы не передаете переменную явно определенного типа.

+0

Не забывайте о правилах продвижения. –