LINUX.ORG.RU

Объясните разницу между int и unsigned int

 ,


0

2

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

    int a=25.5;
    cout << a+75 << endl;
    cin.get();
    return 0;
то выведется только 100. Оно и понятно, ведь инт целочисленный. чтобы пример посчитался со значением после запятой нужно указывать что это float. однако, если сделать вот так
    unsigned int a=-50;
    cout << a+75 << endl;
    cin.get();
    return 0;
то выведется 25, почему? unsigned же это беззнаковый, он не может в минус. а считает все правильно. объясните кто-нибудь

Если в unsigned int записывают значение, которое не помещается в диапазон допустимых значений, к числу прибавляется или от числа отнимается 4294967296 до тех пор, пока результат не станет помещаться в диапазон допустимых значений для unsigned int. Здесь предполагается, что unsigned int — 32-битный.

Когда складываются два unsigned int числа, к результату прибавляется или от результата отнимается 4294967296 до тех пор, пока результат не станет помещаться в диапазон допустимых значений для unsigned int. Это число ты и видишь.

А, да. Когда к unsigned int прибавляют int, а 25 это int, то int сначала приводится к значению, допустимому для unsigned int. Всё теми же прибавлениями и вычитаниями 4294967296. А уже потом два unsigned int складываются.

i-rinat ★★★★★
()
Последнее исправление: i-rinat (всего исправлений: 1)
Ответ на: комментарий от i-rinat

не очень понял. вот я в unsigned ставлю -100, оно не подходит. К нему прибавляется 4294967296, далее по коду прибавляется 75,(кстати, почему 75 это int? оно не может быть unsigned int?) каким образом по итогу выходит 25?

PURGEN143 ★
() автор топика

1. Прочитай, как положительные и отрицательные числа записываются в двоичной системе.
2. Запиши все приведённые числа в двоичной системе.
3. Проведи над ними все описанные в посте операции. Не забывая про разрядность (т.е. отбрасывая все старшие разряды, которые не укладываются в размер типа).
4. Переведи полученное обратно в десятичную систему. Примерно на этом этапе ты уже должен будешь всё понять.

gremlin_the_red ★★★★★
()
Последнее исправление: gremlin_the_red (всего исправлений: 1)
Ответ на: комментарий от PURGEN143

когда ты кладёшь в 32-ух битный unsigned int отрицательное число происходит переполнение двоичного числа и кладётся (0 - 50) попробуйте выполнить в двоичном виде - операция побитово выполнится, но как бы с вовлечением недоступных битов, т.е. будет выглядеть как будто вы заняли(что равно прибавлению) 33-ий бит которого нет и в ячейку будет сохранено число 2^32 - 50, затем прибавляя 75 вы вновь вызываете переполнение(только в другую сторону) для суммы 2^32 - 50 и 75 - по идее вы должны будете перенести 1 бит в 33 бит, но опять же т.к. его нет получится его отбрасывание эквивалентное вычитанию и получится: 2^32 - 50 + 75 - 2^32 = 25, это более менее представимая в голове интерпретация, в действительности отрицательное число как правило хранится с дополнением до единицы и по сути когда вы просите положить в беззнаковое хранилище отрицательное число a в него кладётся дополненное до единицы вида ~a + 1 или в более простом виде 2^32 - a

Правда это в теории, на практике компилятор в данном случае оптимизирует код и делает во время компиляции расчёты в более широких типах данных, дабы не было переполнений

В целом действительно стоит почитать про хранение чисел на цифровых вычислительных устройствах, например по школьному учебнику информатики(8-9 класс) или по Харрисам

AKonia ★★★
()
Последнее исправление: AKonia (всего исправлений: 9)

Объясните разницу между int и unsigned int

unsigned int — это арифметика в кольце Z_{2^32}. int — это арифметика на Z, кидающая UB при выходе за пределы [-2^31, 2^31), так называемом «переполнении». unsigned переполниться не может

Crocodoom ★★★★★
()
Ответ на: комментарий от PURGEN143

Приводя отрицательное число к беззнаковому ты получаешь число близкое к максимальному, потом ты прибавляешь к нему ещё, тем самым переполняя его, где в итоге 25 и является результатом переполнения.

WitcherGeralt ★★
()
Ответ на: комментарий от PURGEN143

каким образом по итогу выходит 25

Из-за переполнения заворачивается через 0. Т.е. …max-2, max-1, max, 0, 1… Твои -50 будут max-50. Прибавь 75, что получиться?

no-such-file ★★★★★
()

75 это int, а вот 75u это unsigned int. Когда ты кладёшь int в unsigned int туда записывается просто бинарное представление int, если ты выведешь a, результат будет не -50. Но при сложении со знаковым типом, а именно он выберется как приоритетный, a будет приведено к знаковому.

pon4ik ★★★★★
()

signed от unsigned отличается при сдвиге вправо, при переполнении и оптимизация, а в процессоре - только при интерпретации флагов, выставляемых по результатам операции.

salozar
()
Ответ на: комментарий от pon4ik

Но при сложении со знаковым типом, а именно он выберется как приоритетный, a будет приведено к знаковому.

Нет же. Если битность одинаковая, то знаковое приводится к беззнаковому, а не беззнаковое к знаковому.

i-rinat ★★★★★
()

Можно начать с понимание, что самое большое беззнаковое целое число любой разраядности это -1 :)

Oleg_Iu ★
()

и вообще число со знаком меньше нуля(-Х), это число без знака Y, которое при сложении с X даст 0

то есть 32битное -X на самом деле = 2^32-X

salozar
()
Ответ на: комментарий от i-rinat

Прикольный квиз, спасибки.

Хотя вариант от @xaizek выглядит полезнее в перспективе «не держи это в голове». Т.к. по факту код из оп поста это то, что должно даже не проходить билд :)

pon4ik ★★★★★
()
Ответ на: комментарий от pon4ik

Т.к. по факту код из оп поста это то, что должно даже не проходить билд :)

Билд и не проходит

 error: implicit conversion changes signedness: 'int' to 'unsigned int' [-Werror,-Wsign-conversion]
    unsigned int a=-50;
                 ~ ^~~
fsb4000 ★★★★★
()

Я так понимаю, сделать cout << a ты даже не попытался?

Miguel ★★★★★
()

unsigned - это всего лишь число без знакового бита. поэтому когда ты кладёшь в него -50, то в него ложится -50, но т.к. знакового бита нет, то число представляется без знака. это называется underflow.

когда ты делаешь +75, ты делаешь -50+75, это 25, что и выводится. так может быть не на всех платформах, поэтому это называется «неопределённое поведение», стандарт языка не определяет каким должно быть поведение в этом случае.

зачем это нужно: без знакового бита можно хранить в два раза больше значений чем со знаковым битом. short int - это -32768..32767, unsigned short int - это 0..65535.

anonymous
()
Ответ на: комментарий от anonymous

в два раза больше значений

Не значений, а большее по величине значение.

AKonia ★★★
()
Последнее исправление: AKonia (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему: топик перемещен в архив.