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)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.