2014-01-14 2 views
0

Я новичок здесь, так что извините, если это базовое, но что мне здесь не хватает? Это всего лишь фиктивный код:Разделение целых чисел на C++ не работает должным образом

#include <iostream> 
using namespace std; 

int main() { 
    unsigned int a, b, c; 
    int d; 
    a = 10E06; 
    b = 25E06; 
    c = 4096; 
    d = (a - b)/c; 
    std::cout << d << std::endl; 
    return 0; 
} 

cout - это печать 1044913 вместо -3662. Если я дам a и b, то проблема решена. Есть проблема переполнения или что-то еще?

+2

Собираетесь ли вы с предупреждениями? Нет? Почему нет? –

+0

Что это, научная нотация? Хекс-номерам обычно предшествует '0x' –

+1

Почему, по-вашему, это связано с делением? – juanchopanza

ответ

4

Это потому, что само по себе является (a-b) без знака:

#include <iostream> 
using namespace std; 

int main() { 
    unsigned int a, b, c; 
    int d; 
    a = 10E06; 
    b = 25E06; 
    c = 4096; 
    d = (a - b)/c; 
    std::cout << (a-b) << std::endl; // 4279967296 
    std::cout << d << std::endl; // 1044913 
    return 0; 
} 

Переход от unsigned к int происходит, когда d назначается, а не раньше.

So (a-b)/c должно быть без знака с a,b,c.

3

Операции между неподписанными номерами дают неподписанные числа. Это зависит от вас, чтобы убедиться, что операции имеют смысл, или защищать от противоположного.

Если у вас есть unsigned int a = 2, b = 3;, что, по вашему мнению, значение a-b будет?

2

Поскольку все b и c объявлены как unsigned, вывод вычисления (a-b)/c будет неподписанным. Поскольку вычисление предоставленных вами значений не может быть правильно представлено без знака, все становится немного грязным. Затем значение unsigned присваивается d, и даже если оно подписано, значение уже искажено.

Я также отмечу, что обозначение 10E06 представляет собой число с плавающей запятой, которое затем неявно приводится к неподписанному int. В зависимости от конкретного значения с плавающей запятой это может быть или не быть выбрано, как ожидалось.

1

Вы хотите, чтобы ваш результат принял знак. Поэтому вы должны объявить переменные как подписанные int или просто int. Это даст желаемый результат. Если вы нажмете a и b до конца, a-b будет длинным и, следовательно, примет знак. Следующее - это решение.

int main() { 
    int a, b, c; 
    int d; 
    a = 10E06; 
    b = 25E06; 
    c = 4096; 
    d = (a - b)/c; 
    std::cout << d << std::endl; 
    return 0; 
} 

Если вы хотите рациональные числа вы должны использовать двойников или плавать (atlhough это не даст другой результат для данного конкретного случая).

int main() { 
    double a, b, c; 
    double d; 
    a = 10E06; 
    b = 25E06; 
    c = 4096; 
    d = (a - b)/c; 
    std::cout << d << std::endl; 
    return 0; 
} 
1

Из-за путями C++ (и многие другие C на основе языков) имеет дело с операторами, когда без знака ставятся в выражение, это выражение возвращает значение без знака, а не дотянули в таинственном межтипового что можно ожидать.

Шаг за шагом:

  • (a - b) вычитает 25E06 из 10E06, которые обычно возвращают -15E06, это без знака, так что это обернуто вокруг целой кучей мусора.
  • Этот хлам затем делится на c, и оба входа являются неподписанными, поэтому выходной сигнал также является неподписанным.
  • Наконец, это чучело в знаковый междунар, оставаясь при 1044913.

«неподписанных Int» это тип так же, как поплавок и BOOL, даже если это требует двух ключевых слов.Если вы хотите, чтобы он превращался в подписанный int для этого вычисления, вы должны либо убедиться, что a, b и c подписаны (удалить ключевое слово unsigned), либо использовать их как таковые, когда помещаете их в выражение, например: d = ((signed)a - (signed)b)/(signed)c;

Смежные вопросы