Что такое беззнаковая переменная
Беззнаковая арифметика в Java
Преобразование byte в short (int, long)
Обычный каст (int) myByte выполнит расширение до 32 бит со знаком — это означает, что если старший бит байта был установлен в 1, то результатом будет то же самое отрицательное число, но записанное в 32-битном формате:
Сравнение без учёта знака
Для беззнакового сравнения есть лаконичная формула:
Сложение, вычитание и умножение
А вот здесь приятный сюрприз — эти операции выполняются корректно в любом случае. Но в выражениях необходимо тщательно следить за тем, чтобы операции выполнялись с числами одного типа, так как любые неявные преобразования выполняются с расширением знака, и могут приводить к результатам, отличным от ожидаемых. Коварство таких багов в том, что ошибочный сценарий может выполняться очень редко.
Деление
Чтобы код компилировался, придётся также позаимствовать реализацию compare(long, long) :
и Longs.compare(long, long) + flip(long) :
Побитовые сдвиги
The shift arithmetic left (SAL) and shift logical left (SHL) instructions perform the same operation; they shift the bits in the destination operand to the left (toward more significant bit locations). For each shift count, the most significant bit of the destination operand is shifted into the CF flag, and the least significant bit is cleared (see Figure 7-7 in the Intel®64 and IA-32 Architectures Software Developer’sManual, Volume 1).
То есть SAL добавили просто для симметрии, с учётом того, что для сдвига вправо есть разделение на логический и арифметический. Ну а Гослинг решил не заморачиваться (и, думается, правильно сделал).
Знаковый и безнаковый тип?
Объясните пожалуйста! Изучаю Си. Я немного не понимаю, чем отличается знаковый тип от безнакового? Знаковый тип это:
1) short, int от –32 767 до 32 767?
2) Или наборот unsigned short, unsigned int от 0 до 65 535?
В общем, да. Правда, int нынче обычно длиннее. Посмотри, например, это: http://ru.cppreference.com/w/cpp/language/types
Знаковый — это у которого знак (+/-) есть. Беззнаковый — это у которого нет.
Знаковый (signed) — у чисел важен знак — плюс или минус, то есть числа могут быть как отрицательные, так и положительные и, соответственно, могут быть меньше нуля.
А на самом деле компьютеру вообще пофиг, ну, может только при делении/умножении другие инструкции используются. Ты можешь попробовать «привести» беззнаковый тип к знаковому и проверить какие будут значения для чисел больше 32767. Это интересно.
В каком бите хранится знак числа?
Отрицательных чисел обычно на 1 больше чем положительных (-32768) потому что https://en.wikipedia.org/wiki/Two’s_complement
Я немного не понимаю, чем отличается знаковый тип от безнакового
как интерпритируется(тут тебе стоит разобратся кем/чем) битовая строка заданного некоторого(|одно)байтного размера.
см любую конечную арифметику (вычеты. )
погугли бинарные представления чисел и как компы видят отрицательные числа, сразу все станет понятно
Hufoc, где в каком универе изучают этот древний сруктурный язык?
В каком современном языке нет различий между знаковыми и беззнаковыми числами? JavaScript?
qulinxao никогда не работай преподователем, тебя никто, никогда не поймёт. Ты не умеешь излагать на разговорном языке.
В каком современном языке нет различий между знаковыми и беззнаковыми числами? JavaScript?
Чувак был задан вопрос о том, где в каком универе преподают этот древний язык. А о наличиях и отсутствях типов в современных ЯП никто не интересовался.
Эст-еблан Гарсия учись логически мыслить.
В каком месте ты вообще увидел здесь логическое мышление. Более того, тебе не следовало задавать этот вопрос.
В каком месте ты вообще увидел здесь логическое мышление.
У тебя с головой всё в порядке?
Более того, тебе не следовало задавать этот вопрос.
Почему же, интересено в каком таком универе преподают этот древний язык.
В си целые числа по умолчанию знаковые. Беззнаковые нужно объявлять особо. Многие считают это решение странным и сомнительным. Ведь диапазон 0 … 2^n-1 намного предпочтительнее с философской точки зрения.
Типы данных в языке Си
Тип данных определяет множество значений, набор операций, которые можно применять к таким значениям и способ реализации хранения значений и выполнения операций.
Язык Си поддерживает статическую типизацию, и типы всех используемых в программе данных должны быть указаны перед ее компиляцией.
Различают простые, составные и прочие типы данных.
Простые данные
Простые данные можно разделить на
Составные (сложные) данные
Другие типы данных
Программа, написанная на языке Си, оперирует с данными различных типов. Все данные имеют имя и тип. Обращение к данным в программе осуществляется по их именам (идентификаторам).
Идентификатор — это последовательность, содержащая не более 32 символов, среди которых могут быть любые буквы латинского алфавита a — z, A — Z, цифры 0 — 9 и знак подчеркивания (_). Первый символ идентификатора не должен быть цифрой.
Несмотря на то, что допускается имя, имеющее до 32 символов, определяющее значение имеют только первые 8 символов. Помимо имени, все данные имеют тип. Указание типа необходимо для того, чтобы было известно, сколько места в оперативной памяти будет занимать данный объект.
Компилятор языка Си придерживается строгого соответствия прописных и строчных букв в именах идентификаторов и лексем.
INT a=2;
b = A + 3; // идентификатор А не объявлен
b = a + 3; // идентификатор b не объявлен
Целочисленные данные
Целочисленные данные могут быть представлены в знаковой и беззнаковой форме.
Основные типы и размеры целочисленных данных:
Количество бит | Беззнаковый тип | Знаковый тип |
8 | unsigned char 0…255 | char -128…127 |
16 | unsigned short 0…65535 | short -32768…32767 |
32 | unsigned int | int |
64 | unsigned long int | long int |
Вещественные данные
Вещественный тип предназначен для представления действительных чисел. Вещественные числа представляются в разрядной сетке машины в нормированной форме.
Нормированная форма числа предполагает наличие одной значащей цифры (не 0) до разделения целой и дробной части. Такое представление умножается на основание системы счисления в соответствующей степени. Например, число 12345,678 в нормированной форме можно представить как
12345,678 = 1,2345678·10 4
Число 0,009876 в нормированной форме можно представить как
В двоичной системе счисления значащий разряд, стоящий перед разделителем целой и дробной части, может быть равен только 1. В случае если число нельзя представить в нормированной форме (например, число 0), значащий разряд перед разделителем целой и дробной части равен 0.
В общем случае вещественное число в разрядной сетке вычислительной машины можно представить в виде 4 полей.
Различают три основных типа представления вещественных чисел в языке Си:
Тип | Обозна- чение в Си | Кол-во бит | Биты степени | Мантисса | Сдвиг |
простое | float | 32 | 30…23 | 22…0 | 127 |
двойной точности | double | 64 | 62…52 | 51…0 | 1023 |
двойной расширен- ной точности | long double | 80 | 78…64 | 62…0 | 16383 |
Как видно из таблицы, бит целое у типов float и double отсутствует. При этом диапазон представления вещественного числа состоит из двух диапазонов, расположенных симметрично относительно нуля. Например, диапазон представления чисел типа float можно представить в виде:
Для представления числа в двоичной системе счисления преобразуем отдельно целую и дробную части:
178,12510 = 10110010,0012=1,0110010001·2 111
Для преобразования в нормированную форму осуществляется сдвиг на 7 разрядов влево).
Для определения степени числа применяем сдвиг:
0111111+00000111 = 10000110.
Символьный тип
Логический тип
Логический тип применяется в логических операциях, используется при алгоритмических проверках условий и в циклах и имеет два значения:
В программе должно быть дано объявление всех используемых данных с указанием их имени и типа. Описание данных должно предшествовать их использованию в программе.
В чем разница между знаковыми и беззнаковыми переменными?
Я видел это в контексте C и C ++, но в чем разница между знаковыми и беззнаковыми переменными?
8 ответов
Хотя обычно их называют «знаковым битом», обычно используемые двоичные значения не имеют истинного знакового бита.
Большинство компьютеров используют арифметику с дополнением до двух. Отрицательные числа создаются путем дополнения до единицы (перевернуть все биты) и добавления единицы:
Знаковые переменные используют один бит для обозначения того, положительные они или отрицательные. Беззнаковые переменные не имеют этого бита, поэтому они могут хранить в том же пространстве большие числа, но только неотрицательные числа, например 0 и выше.
Беззнаковые переменные могут быть только положительными числами, потому что они не могут указывать, что они отрицательные.
Эта способность называется «знаком» или «бит подписи».
Побочным эффектом является то, что без бита подписи у них есть еще один бит, который можно использовать для представления числа, удваивая максимальное число, которое оно может представлять.
Переменные со знаком могут быть 0, положительными или отрицательными.
Беззнаковые переменные могут иметь значение 0 или положительное значение.
Иногда используются беззнаковые переменные, потому что для представления фактического значения можно использовать больше битов. Предоставляя вам больший диапазон. Также вы можете убедиться, что, например, в вашу функцию не будет передано отрицательное значение.
Это всего лишь мои два цента.
Надеюсь, это поможет.
Это может быть не точное определение, но я приведу вам пример: если вы должны были создать случайное число, взяв его из системного времени, здесь использование беззнаковой переменной выгодно, поскольку существует большая область для случайных чисел, поскольку числа со знаком дают как положительные, так и отрицательные числа. Поскольку системное время не может быть отрицательным, мы используем переменную без знака (только положительные числа), и у нас есть более широкий диапазон случайных чисел.
4.5 – Целочисленные типы данных без знака, и почему их следует избегать
Целочисленные типы данных без знака
В предыдущем уроке (4.4 – Целочисленные типы данных со знаком) мы рассмотрели целочисленные типы со знаком, которые представляют собой набор типов, которые могут содержать положительные и отрицательные целые числа, включая 0.
C++ также поддерживает беззнаковые целочисленные типы. Беззнаковые целочисленные значения – это целые числа, которые могут содержать только неотрицательные значения.
Определение беззнаковых целочисленных значений
Диапазоны значений целочисленных типов без знака
Ниже показана таблица, показывающая диапазоны беззнаковых целочисленных типов:
Размер / Тип | Диапазон |
---|---|
1 байт без знака | от 0 до 255 |
2 байт без знака | от 0 до 65 535 |
4 байт без знака | от 0 до 4 294 967 295 |
8 байт без знака | от 0 до 18 446 744 073 709 551 615 |
Диапазон беззнаковой переменной размером n бит составляет от 0 до (2 n )-1.
Целочисленные типы без знака хорошо подходят для сетей и систем с небольшим объемом памяти, когда нет необходимости в отрицательных числах, поскольку беззнаковые целочисленные значения могут хранить бо́льшие положительные числа, не занимая дополнительной памяти.
Напоминание относительно значений со знаком и без знака
Начинающие программисты иногда путаются между значениями со знаком и без знака. Простой способ запомнить разницу: чтобы отличить отрицательные числа от положительных, мы используем знак минус. Если знак не указан, мы предполагаем, что число положительное. Следовательно, целочисленное значение со знаком (целочисленный тип со знаком) может различать положительные и отрицательные числа. Целочисленное значение без знака (целочисленный тип без знака) предполагает, что все значения положительны.
Переполнение целочисленных значений без знака
Что произойдет, если мы попытаемся сохранить число 280 (для представления которого требуется 9 бит) в 1-байтовом (8-битном) целочисленном значении без знака? Ответ – переполнение.
Примечание автора
Как ни странно, в стандарте C++ прямо говорится, что «вычисление с использованием беззнаковых операндов никогда не может переполниться». Это противоречит общему мнению программистов о том, что целочисленное переполнение охватывает случаи как со знаком, так и без знака. Учитывая, что большинство программистов рассмотрело бы этот случай как переполнение, мы будем называть его переполнением, несмотря на утверждения C++ об обратном.
Если значение без знака выходит за пределы допустимого диапазона, оно делится на число, превышающее на единицу наибольшее число, допустимое для заданного типа данных, и сохраняется только остаток.
Число 280 слишком велико, чтобы поместиться в наш 1-байтовый диапазон от 0 до 255. Значение, которое на 1 больше максимального числа для этого типа данных, равно 256. Следовательно, мы делим 280 на 256, получая остаток 24. Остаток 24 – это то, что в итоге сохранится.
Вот еще один способ размышления о том же. Любое число, превышающее наибольшее число, которое может быть представлено заданным типом данных, просто «оборачивается» (или совершает циклический переход). Число 255 находится в диапазоне 1-байтового целочисленного типа, поэтому 255 сохранится нормально. А число 256 находится за пределами диапазона, поэтому оно оборачивается до значения 0. 257 оборачивается до значения 1. 280 оборачивается до значения 24.
Давайте посмотрим на это, используя 2-байтовые целые числа:
Как вы думаете, каким будет результат работы этой программы?
Приведенный выше код в некоторых компиляторах вызывает предупреждение, поскольку компилятор обнаруживает, что целочисленный литерал выходит за пределы допустимого диапазона для данного типа. Если вы всё равно хотите скомпилировать этот код, временно отключите параметр «Treat warnings as errors» (обрабатывать предупреждения как ошибки).
В качестве отступления.
Многие заметные ошибки в истории видеоигр произошли из-за поведения циклического перехода целочисленных значений без знака. В аркадной игре Donkey Kong невозможно пройти уровень 22 из-за бага переполнения, из-за которого у пользователя недостаточно бонусного времени для завершения уровня.
Споры по поводу чисел без знака
Многие разработчики (и некоторые крупные компании, например, Google) считают, что разработчикам следует избегать целочисленных типов без знака.
Во многом это связано с двумя типами поведения, которые могут вызывать проблемы.
На машине автора эта, казалось бы, невинно выглядящая программа дает следующий результат:
Во-вторых, непредвиденное поведение может возникнуть при смешивании целочисленных значений со знаком и без знака. В приведенном выше примере, даже если один из операндов ( x или y ) будет со знаком, другой операнд (беззнаковый) приведет к тому, что операнд со знаком будет преобразован в целочисленное значение без знака, и будет получено такое же поведение!
Рассмотрим следующий фрагмент:
Если вам нужно защитить функцию от отрицательных входных данных, используйте вместо этого утверждение или исключение. Они оба будут рассмотрены позже.
Начинающие программисты часто используют целочисленные типы без знака для представления неотрицательных данных или для того, чтобы воспользоваться дополнительно расширенным диапазоном. Бьярн Страуструп, разработчик C++, сказал: «Использование unsigned int вместо int для получения еще одного бита для представления положительных целых чисел почти никогда не бывает хорошей идеей».
Предупреждение
Избегайте использования числовых типов без знака, за исключением особых случаев или, когда это необходимо.
Не избегайте отрицательных чисел с помощью беззнаковых типов. Если вам нужен больший диапазон, чем предлагает числовой тип со знаком, используйте один из целочисленных типов гарантированной ширины, показанных в следующем уроке (4.6 – Целочисленные типы фиксированной ширины и size_t ).
Если вы всё же используете беззнаковые числа, по возможности избегайте смешивания чисел со знаком и без знака.
Так где же стоит использовать беззнаковые числа?
В C++ всё же есть несколько случаев, когда можно (или необходимо) использовать беззнаковые числа.
Во-первых, числа без знака предпочтительнее при работе с битами (рассматривается в главе O (это заглавная буква «о», а не «0»).
Во-вторых, использование беззнаковых чисел всё еще неизбежно в некоторых случаях, в основном тех, которые связаны с индексацией массивов. Подробнее об этом мы поговорим в уроках по массивам и индексированию массивов.
Также обратите внимание, что, если вы разрабатываете для встраиваемой системы (например, Arduino) или какого-либо другой системы с ограничениями процессора/памяти, использование чисел без знака более распространено и приемлемо (а в некоторых случаях неизбежно) по соображениям производительности.