8 байтовые знаковые целые числа что это
Предыдущая лекция | Содержание | Следующая лекция
Информатика. Лекция №5. Представление чисел в компьютере.
Представление целых чисел в компьютере.
Целые числа являются простейшими числовыми данными, с которыми оперирует ЭВМ. Для целых чисел существуют два представления: беззнаковое (только для неотрицательных целых чисел) и со знаком. Очевидно, что отрицательные числа можно представлять только в знаковом виде. Целые числа в компьютере хранятся в формате с фиксированной запятой.
Представление целых чисел в беззнаковых целых типах.
Для беззнакового представления все разряды ячейки отводятся под представление самого числа. Например, в байте (8 бит) можно представить беззнаковые числа от 0 до 255. Поэтому, если известно, что числовая величина является неотрицательной, то выгоднее рассматривать её как беззнаковую.
Представление целых чисел в знаковых целых типах.
Для представления со знаком самый старший (левый) бит отводится под знак числа, остальные разряды — под само число. Если число положительное, то в знаковый разряд помещается 0, если отрицательное — 1. Например, в байте можно представить знаковые числа от -128 до 127.
Прямой код числа.
Представление числа в привычной форме «знак»-«величина», при которой старший разряд ячейки отводится под знак, а остальные — под запись числа в двоичной системе, называется прямым кодом двоичного числа. Например, прямой код двоичных чисел 1001 и -1001 для 8-разрядной ячейки равен 00001001 и 10001001 соответственно.
Положительные числа в ЭВМ всегда представляются с помощью прямого кода. Прямой код числа полностью совпадает с записью самого числа в ячейке машины. Прямой код отрицательного числа отличается от прямого кода соответствующего положительного числа лишь содержимым знакового разряда. Но отрицательные целые числа не представляются в ЭВМ с помощью прямого кода, для их представления используется так называемый дополнительный код.
Дополнительный код числа.
Дополнительный код положительного числа равен прямому коду этого числа. Дополнительный код отрицательного числа m равен 2 k -|m|, где k — количество разрядов в ячейке.
Как уже было сказано, при представлении неотрицательных чисел в беззнаковом формате все разряды ячейки отводятся под само число. Например, запись числа 243=11110011 в одном байте при беззнаковом представлении будет выглядеть следующим образом:
| 1 | 1 | 1 | 1 | 0 | 0 | 1 | 1 |
При представлении целых чисел со знаком старший (левый) разряд отводится под знак числа, и под собственно число остаётся на один разряд меньше. Поэтому, если приведённое выше состояние ячейки рассматривать как запись целого числа со знаком, то для компьютера в этой ячейке записано число -13 (243+13=256=28).
Но если это же отрицательное число записать в ячейку из 16-ти разрядов, то содержимое ячейки будет следующим:
| 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 | 1 |
Знаковый разряд
Возникает вопрос: с какой целью отрицательные числа записываются в виде дополнительного кода и как получить дополнительный код отрицательного числа?
Дополнительный код используется для упрощения выполнения арифметических операций. Если бы вычислительная машина работала с прямыми кодами положительных и отрицательных чисел, то при выполнении арифметических операций следовало бы выполнять ряд дополнительных действий. Например, при сложении нужно было бы проверять знаки обоих операндов и определять знак результата. Если знаки одинаковые, то вычисляется сумма операндов и ей присваивается тот же знак. Если знаки разные, то из большего по абсолютной величине числа вычитается меньшее и результату присваивается знак большего числа. То есть при таком представлении чисел (в виде только прямого кода) операция сложения реализуется через достаточно сложный алгоритм. Если же отрицательные числа представлять в виде дополнительного кода, то операция сложения, в том числе и разного знака, сводится к из поразрядному сложению.
Для компьютерного представления целых чисел обычно используется один, два или четыре байта, то есть ячейка памяти будет состоять из восьми, шестнадцати или тридцати двух разрядов соответственно.
Алгоритм получения дополнительного кода отрицательного числа.
- модуль отрицательного числа представить прямым кодом в k двоичных разрядах;
- значение всех бит инвертировать:все нули заменить на единицы, а единицы на нули(таким образом, получается k-разрядный обратный код исходного числа);
- к полученному обратному коду прибавить единицу.
Пример:
Получим 8-разрядный дополнительный код числа -52:
00110100 - число |-52|=52 в прямом коде 11001011 - число -52 в обратном коде 11001100 - число -52 в дополнительном коде
Можно заметить, что представление целого числа не очень удобно изображать в двоичной системе, поэтому часто используют шестнадцатеричное представление:
1100 1100 С С
Представление вещественных чисел в компьютере.
Для представления вещественных чисел в современных компьютерах принят способ представления с плавающей запятой. Этот способ представления опирается на нормализованную (экспоненциальную) запись действительных чисел.
Как и для целых чисел, при представлении действительных чисел в компьютере чаще всего используется двоичная система, следовательно, предварительно десятичное число должно быть переведено двоичную систему.
Нормализованная запись числа.
Нормализованная запись отличного от нуля действительного числа — это запись вида a= m*P q , где q — целое число (положительное, отрицательное или ноль), а m — правильная P-ичная дробь, у которой первая цифра после запятой не равна нулю, то есть . При этом m называется мантиссой числа, q — порядком числа.
- 3,1415926 = 0, 31415926 * 10 1 ;
- 1000=0,1 * 10 4 ;
- 0,123456789 = 0,123456789 * 10 0 ;
- 0,00001078 = 0,1078 * 8 -4 ; (порядок записан в 10-й системе)
- 1000,00012 = 0, 100000012 * 2 4 .
Нормализованная экспоненциальная запись числа — это запись вида a= m*P q , где q — целое число (положительное, отрицательное или ноль), а m — P-ичная дробь, у которой целая часть состоит из одной цифры. При этом (m-целая часть) называется мантиссой числа, q — порядком числа.
Представление чисел с плавающей запятой.
При представлении чисел с плавающей запятой часть разрядов ячейки отводится для записи порядка числа, остальные разряды — для записи мантиссы. По одному разряду в каждой группе отводится для изображения знака порядка и знака мантиссы. Для того, чтобы не хранить знак порядка, был придуман так называемый смещённый порядок, который рассчитывается по формуле 2 a-1 +ИП, где a — количество разрядов, отводимых под порядок.
Пример:
Если истинный порядок равен -5, тогда смещённый порядок для 4-байтового числа будет равен 127-5=122.
Алгоритм представления числа с плавающей запятой.
- Перевести число из p-ичной системы счисления в двоичную;
- представить двоичное число в нормализованной экспоненциальной форме;
- рассчитать смещённый порядок числа;
- разместить знак, порядок и мантиссу в соответствующие разряды сетки.
Можно заметить, что представление действительного числа не очень удобно изображать в двоичной системе, поэтому часто используют шестнадцатеричное представление:
Окончательный ответ: C1CD0000.
Числовые типы данных (Visual Basic)
Visual Basic предоставляет несколько числовых типов данных для обработки чисел в различных представлениях. Целочисленные типы представляют только целые числа (положительные, отрицательные и нулевые), а неинтегральные типы — числа с целыми числами и дробными частями.
Таблицу, показывающую параллельное сравнение типов данных Visual Basic, см. в разделе Типы данных.
Целочисленные числовые типы
Целочисленные типы данных представляют только числа без дробных частей.
Подписанные целочисленные типы данных: SByte Data Type (8-bit), Short Data Type (16-bit), Integer Data Type (32-bit) и Long Data Type (64-bit). Если переменная всегда хранит целые числа, а не дробные числа, объявите ее как один из этих типов.
Целочисленные типы без знака: байтовый тип данных (8-разрядный), тип данных UShort (16-разрядный), тип данных UInteger (32-разрядная версия) и тип данных ULong (64-разрядная версия). Если переменная содержит двоичные данные или данные неизвестного характера, объявите ее как один из этих типов.
Производительность
Арифметические операции выполняются быстрее с целочисленными типами, чем с другими типами данных. Они являются самыми быстрыми Integer с типами и UInteger в Visual Basic.
Большие целые числа
Если требуется содержать целое число, превышающее Integer размер типа данных, можно использовать Long этот тип данных. Long переменные могут содержать числа от -9 223 372 036 854 775 808 до 9 223 372 036 854 775 807. Операции с Long выполняются немного медленнее, чем с Integer .
Если вам нужны еще большие значения, можно использовать тип данных Decimal. Вы можете хранить числа от -79 228 162 514 264 337 593 543 950 335 до 79 228 162 514 264 337 593 543 950 335 в переменной Decimal , если вы не используете десятичные разряды. Однако операции с числами Decimal выполняются значительно медленнее, чем с любым другим числовым типом данных.
Небольшие целые числа
Если вам не нужен полный Integer диапазон данных, можно использовать Short тип данных, который может содержать целые числа от –32 768 до 32 767. Для наименьшего целочисленного диапазона SByte тип данных содержит целые числа от –128 до 127. Если у вас очень большое количество переменных, которые содержат небольшие целые числа, среда CLR иногда может хранить Short переменные и SByte более эффективно и экономить потребление памяти. Однако операции с Short и SByte выполняются несколько медленнее, чем с Integer .
Целые числа без знака
Если известно, что переменной никогда не требуется содержать отрицательное число, можно использовать неподписанные типы Byte , UShort , UInteger и ULong . Каждый из этих типов данных может содержать положительное целое число, в два раза больше соответствующего типа со знаком ( SByte , , Short Integer и Long ). С точки зрения производительности каждый неподписанный тип точно так же эффективен, как и соответствующий тип со знаком. В частности, UInteger разделяет с Integer отличием от того, что является наиболее эффективным из всех элементарных числовых типов данных.
Неинтегральные числовые типы
Неинтегральные типы данных представляют числа как с целочисленной, так и с дробной частями.
Неинтегральные числовые типы данных: Decimal (128-разрядная фиксированная точка), Один тип данных (32-разрядная плавающая запятая) и Тип данных Double (64-разрядная точка с плавающей запятой). Все они являются подписанными типами. Если переменная может содержать дробь, объявите ее как один из этих типов.
Decimal не является типом данных с плавающей запятой. Decimal Числа имеют двоичное целочисленное значение и коэффициент масштабирования целого числа, указывающий, какая часть значения является десятичной дроби.
Для денежных значений можно использовать Decimal переменные. Преимуществом является точность значений. Тип Double данных работает быстрее и требует меньше памяти, но при этом могут возникать ошибки округления. Тип Decimal данных сохраняет полную точность до 28 десятичных разрядов.
Числа с плавающей запятой ( Single и Double ) имеют больше диапазонов, чем Decimal числа, но могут быть подвержены ошибкам округления. Типы с плавающей запятой поддерживают меньше значимых цифр, чем Decimal , но могут представлять значения большей величины.
Неинтегральные числовые значения могут быть выражены как mmmEeee, в котором mmm — мантисса (значимые цифры), а eee — показатель степени (степень 10). Самые высокие положительные значения неинтегральных типов — 7,92281625142643375935033950335E+28 для Decimal , 3,4028235E+38 для Single и 1,79769313486231570E+308 для Double .
Производительность
Double является наиболее эффективным из дробных типов данных, так как процессоры на текущих платформах выполняют операции с плавающей запятой с двойной точностью. Однако операции с не Double так быстры, как с целочисленными типами, такими как Integer .
Малые величины
Для чисел с наименьшей возможной величиной (ближе всего к 0) Double переменные могут содержать числа от -4,94065645841246544E-324 для отрицательных значений и 4,94065645841246544E-324 для положительных значений.
Малые дробные числа
Если вам не нужен полный Double диапазон данных, можно использовать Single тип данных, который может содержать числа с плавающей запятой от -3,4028235E+38 до 3,4028235E+38. Наименьшие величины для Single переменных — -1,401298E-45 для отрицательных значений и 1,401298E-45 для положительных значений. При наличии очень большого количества переменных, которые содержат небольшие числа с плавающей запятой, среда CLR иногда может более эффективно хранить переменные Single и экономить потребление памяти.
См. также раздел
- Простые типы данных
- Символьные типы данных
- Прочие типы данных
- Устранение неполадок, связанных с типами данных
- Практическое руководство. Вызов функции Windows, принимающей значение беззнакового типа
Совместная работа с нами на GitHub
Источник этого содержимого можно найти на GitHub, где также можно создавать и просматривать проблемы и запросы на вытягивание. Дополнительные сведения см. в нашем руководстве для участников.
Целочисленные типы (справочник по C#)
Целочисленные типы представляют целые числа. Все целочисленные типы являются типами значений. Они также простые типы и могут быть инициализированы с помощью литерала. Все целочисленные типы поддерживают арифметические операторы, побитовые логические операторы, операторы сравнения и равенства.
Характеристики целочисленных типов
C# поддерживает следующие предварительно определенные целочисленные типы:
| Ключевое слово или тип C# | Диапазон | Size | Тип .NET |
|---|---|---|---|
| sbyte | От -128 до 127 | 8-разрядное целое число со знаком | System.SByte |
| byte | От 0 до 255 | 8-разрядное целое число без знака | System.Byte |
| short | От −32 768 до 32 767 | 16-разрядное целое число со знаком | System.Int16 |
| ushort | От 0 до 65 535 | 16-разрядное целое число без знака | System.UInt16 |
| int | От −2 147 483 648 до 2 147 483 647 | 32-разрядное целое число со знаком | System.Int32 |
| uint | От 0 до 4 294 967 295 | 32-разрядное целое число без знака | System.UInt32 |
| long | От −9 223 372 036 854 775 808 до 9 223 372 036 854 775 807 | 64-разрядное целое число со знаком | System.Int64 |
| ulong | От 0 до 18 446 744 073 709 551 615 | 64-разрядное целое число без знака | System.UInt64 |
| nint | Зависит от платформы (вычисляемой во время выполнения) | 32- или 64-разрядное целое число со знаком | System.IntPtr |
| nuint | Зависит от платформы (вычисляемой во время выполнения) | 32- или 64-разрядное целое число без знака | System.UIntPtr |
Во всех строках таблицы, кроме двух последних, каждое ключевое слово типа C# из крайнего левого столбца является псевдонимом для соответствующего типа .NET. Ключевое слово и имя типа .NET являются взаимозаменяемыми. Например, следующие объявления объявляют переменные одного типа:
int a = 123; System.Int32 b = 123;
Типы nint и nuint в последних двух строках таблицы являются целыми числами собственного размера. Для определения целых чисел собственного размера можно использовать nint и nuint ключевое слово. Эти целые числа будут 32-разрядными при использовании в 32-битных процессах и 64-разрядными при использовании в 64-битных процессах. Их можно использовать для сценариев взаимодействия, с низкоуровневыми библиотеками и для оптимизации производительности в сценариях, где часто выполняются математические операции с целыми числами.
Целочисленные типы собственного размера представляются внутренне как типы .NET System.IntPtr и System.UIntPtr. Начиная с C# 11, и nint nuint типы являются псевдонимами для базовых типов.
По умолчанию все целочисленные типы имеют значение 0 .
Каждый из целочисленных типов имеет MinValue и MaxValue свойства, обеспечивающие минимальное и максимальное значение этого типа. Эти свойства являются константами во время компиляции, за исключением случаев собственных типов ( nint и nuint ). MaxValue Свойства MinValue вычисляются во время выполнения для собственных типов. Размеры этих типов зависят от параметров процесса.
Используйте структуру System.Numerics.BigInteger, чтобы представить целое число со знаком без верхней и нижней границ.
Целочисленные литералы
Целочисленные литералы могут быть:
- десятичным числом: без префикса;
- шестнадцатеричным числом: с префиксом 0x или 0X ;
- binary: с 0b префиксом или 0B префиксом
В приведенном ниже коде показан пример каждого из них.
var decimalLiteral = 42; var hexLiteral = 0x2A; var binaryLiteral = 0b_0010_1010;
В предыдущем примере также показано использование _ в качестве разделителя цифр. Цифровой разделитель можно использовать со всеми видами числовых литералов.
Тип целочисленного литерала определяется его суффиксом следующим образом:
-
Если литерал не имеет суффикса, его типом будет первый из следующих типов, в котором может быть представлено его значение: int , uint , long , ulong .
Примечание. Литералы интерпретируется как положительные значения. Например, литерал 0xFF_FF_FF_FF представляет число 4294967295 типа uint , хотя он имеет то же битовое представление, что и число -1 типа int . Если вам требуется значение определенного типа, приведите литерал к этому типу. Используйте оператор unchecked , если представить значение литерала в целевом типе невозможно. Например, unchecked((int)0xFF_FF_FF_FF) выдает -1 .
Примечание. Строчную букву l можно использовать в качестве суффикса. Однако при этом выдается предупреждение компилятора, так как букву l можно перепутать с цифрой 1 . Для ясности используйте L .
Если значение, представленное целочисленным литералом, превышает UInt64.MaxValue, происходит ошибка компиляции CS1021.
Если определенный тип целочисленного литерала — int , а значение, представленное литералом, находится в диапазоне целевого типа, значение можно неявно преобразовать в sbyte , byte , short , ushort , uint , ulong , nint или nuint :
byte a = 17; byte b = 300; // CS0031: Constant value '300' cannot be converted to a 'byte'
Как показано в предыдущем примере, если значение литерала не находится в диапазоне конечного типа, возникает ошибка компилятора CS0031 .
Можно также использовать приведение для преобразования значения, представленного целочисленным литералом, в тип, отличный от определенного типа литерала:
var signedByte = (sbyte)42; var longVariable = (long)42;
Преобразования
Любой целочисленный тип можно преобразовать в любой другой целочисленный тип. Если целевой тип может хранить все значения исходного типа, преобразование является неявным. В противном случае необходимо использовать выражение приведения для выполнения явного преобразования. Для получения дополнительной информации см. статью Встроенные числовые преобразования.
Целые числа собственного размера
Типы целых чисел собственного размера имеют особое поведение, так как хранилище определяется естественным целым числом на целевом компьютере.
-
Чтобы узнать размер целого числа собственного размера во время выполнения, используйте sizeof() . Но код должен компилироваться в контексте unsafe. Например:
Console.WriteLine($"size of nint = "); Console.WriteLine($"size of nuint = "); // output when run in a 64-bit process //size of nint = 8 //size of nuint = 8 // output when run in a 32-bit process //size of nint = 4 //size of nuint = 4
Console.WriteLine($"nint.MinValue = "); Console.WriteLine($"nint.MaxValue = "); Console.WriteLine($"nuint.MinValue = "); Console.WriteLine($"nuint.MaxValue = "); // output when run in a 64-bit process //nint.MinValue = -9223372036854775808 //nint.MaxValue = 9223372036854775807 //nuint.MinValue = 0 //nuint.MaxValue = 18446744073709551615 // output when run in a 32-bit process //nint.MinValue = -2147483648 //nint.MaxValue = 2147483647 //nuint.MinValue = 0 //nuint.MaxValue = 4294967295
- для nint : Int32.MinValue–Int32.MaxValue.
- для nuint : UInt32.MinValue–UInt32.MaxValue.
nint a = 42 nint a = (nint)42;
Спецификация языка C#
Дополнительные сведения см. в следующих разделах статьи Спецификация языка C#:
- Целочисленные типы
- Целочисленные литералы
- Целочисленные типы собственного размера
- C# 11 — числовой IntPtr и UIntPtr
См. также
- справочник по C#
- Типы значений
- Типы с плавающей запятой
- Строки стандартных числовых форматов
- Числовые значения в .NET
Совместная работа с нами на GitHub
Источник этого содержимого можно найти на GitHub, где также можно создавать и просматривать проблемы и запросы на вытягивание. Дополнительные сведения см. в нашем руководстве для участников.
Представление вещественных чисел
Вещественные числа обычно представляются в виде чисел с плавающей запятой. Числа с плавающей запятой — один из возможных способов представления действительных чисел, который является компромиссом между точностью и диапазоном принимаемых значений, его можно считать аналогом экспоненциальной записи чисел, но только в памяти компьютера.
Число с плавающей запятой состоит из набора отдельных двоичных разрядов, условно разделенных на так называемые знак (англ. sign), порядок (англ. exponent) и мантиссу (англ. mantis). В наиболее распространённом формате (стандарт IEEE 754) число с плавающей запятой представляется в виде набора битов, часть из которых кодирует собой мантиссу числа, другая часть — показатель степени, и ещё один бит используется для указания знака числа ( [math]0[/math] — если число положительное, [math]1[/math] — если число отрицательное). При этом порядок записывается как целое число в коде со сдвигом, а мантисса — в нормализованном виде, своей дробной частью в двоичной системе счисления. Вот пример такого числа из [math]16[/math] двоичных разрядов:
| Знак | |||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Порядок | Мантисса | ||||||||||||||
| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 14 | 10 | 9 | 0 | ||||||||||||
Знак — один бит, указывающий знак всего числа с плавающей точкой. Порядок и мантисса — целые числа, которые вместе со знаком дают представление числа с плавающей запятой в следующем виде:
[math](-1)^S \times M \times B^E[/math] , где [math]S[/math] — знак, [math]B[/math] — основание, [math]E[/math] — порядок, а [math]M[/math] — мантисса. Десятичное число, записываемое как [math] ReE[/math] , где [math]R[/math] — число в полуинтервале [math][1; 10)[/math] , [math]E[/math] — степень, в которой стоит множитель [math]10[/math] ; в нормализированной форме модуль [math]R[/math] будет являться мантиссой, а [math]E[/math] — порядком, а [math]S[/math] будет равно [math]1[/math] тогда и только тогда, когда [math]R[/math] принимает отрицательное значение. Например, в числе [math]-2435e9[/math]
- [math]S[/math] [math]=[/math] [math]1[/math]
- [math]B[/math] [math]=[/math] [math]10[/math]
- [math]M[/math] [math]=[/math] [math]2435[/math]
- [math]E[/math] [math]=[/math] [math]9[/math]
Порядок также иногда называют экспонентой или просто показателем степени.
При этом лишь некоторые из вещественных чисел могут быть представлены в памяти компьютера точным значением, в то время как остальные числа представляются приближёнными значениями.
Более простым вариантом представления вещественных чисел является вариант с фиксированной точкой, когда целая и вещественная части хранятся отдельно. Например, на целую часть отводится всегда [math]X[/math] бит и на дробную отводится всегда [math]Y[/math] бит. Такой способ в архитектурах процессоров не присутствует. Отдаётся предпочтение числам с плавающей запятой, как компромиссу между диапазоном допустимых значений и точностью.
Нормальная и нормализованная форма
Нормальной формой (англ. normal form) числа с плавающей запятой называется такая форма, в которой мантисса (без учёта знака) в десятичной системе находится на полуинтервале [math][0; 1)[/math] . Такая форма записи имеет недостаток: некоторые числа записываются неоднозначно (например, [math]00001[/math] можно записать в 4 формах — [math]00001 \times 10[/math] [math]0[/math] , [math]0001 \times 10[/math] [math]−1[/math] , [math]001 \times 10[/math] [math]−2[/math] , [math]01 \times 10[/math] [math]−3[/math] ), поэтому распространена также другая форма записи — нормализованная (англ. normalized), в которой мантисса десятичного числа принимает значения от [math]1[/math] (включительно) до [math]10[/math] (не включительно), а мантисса двоичного числа принимает значения от [math]1[/math] (включительно) до [math]2[/math] (не включительно). То есть в мантиссе слева от запятой до применения порядка находится ровно один знак. В такой форме любое число (кроме [math]0[/math] ) записывается единственным образом. Ноль же представить таким образом невозможно, поэтому стандарт предусматривает специальную последовательность битов для задания числа [math]0[/math] (а заодно и некоторых других полезных чисел, таких как [math]-\infty[/math] и [math]+\infty[/math] ). Так как старший двоичный разряд (целая часть) мантиссы вещественного числа в нормализованном виде всегда равен « [math]1[/math] », то его можно не записывать, сэкономив таким образом один бит, что и используется в стандарте IEEE 754. В позиционных системах счисления с основанием большим, чем [math]2[/math] (в троичной, четверичной и др.), этого замечательного свойства нет (ведь целая часть там может быть не только единицей).
Типы чисел с плавающей точкой (по IEEE 754)
Число половинной точности (Binary16, Half precision)
Число́ полови́нной то́чности — компьютерный формат представления чисел, занимающий в памяти половину машинного слова (в случае 32-битного компьютера — [math]16[/math] бит или [math]2[/math] байта). В силу невысокой точности этот формат представления чисел с плавающей запятой обычно используется в видеокартах, где небольшой размер и высокая скорость работы важнее точности вычислений.
| Знак | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Порядок | Мантисса | |||||||||||||||
| 0 | 0 | 0 | 0 | 0 | 0 | 1, | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 14 | 10 | 9 | 0 | |||||||||||||
Порядок записан со сдвигом [math]-15[/math] . То есть чтобы получить актуально значение порядка нужно вычесть из него сдвиг. Сдвиг можно получить по формуле [math]2^-1[/math] , где [math]b[/math] — число бит, отведенное на хранение порядка (в случае числа половинной точности [math]b=5[/math] ).
Ограничения точности
- Целые от нуля до [math]2048[/math] передаются как есть.
- Целые от [math]2049[/math] до [math]4096[/math] округляются к ближайшему чётному целому.
- Целые от [math]4097[/math] до [math]8192[/math] округляются до ближайшего целого, делящегося нацело на четыре.
- Целые от [math]8193[/math] до [math]16384[/math] округляются до ближайшего целого, делящегося на восемь.
- Целые от [math]16385[/math] до [math]32768[/math] округляются до ближайшего целого, делящегося на шестнадцать.
- Целые от [math]32769[/math] до [math]65535[/math] округляются до ближайшего целого, делящегося на тридцать два.
Число одинарной точности (Binary32, Single precision, float)
Число́ одина́рной то́чности — компьютерный формат представления чисел, занимающий в памяти одно машинное слово (в случае 32-битного компьютера — [math]32[/math] бита или [math]4[/math] байта). Используется для работы с вещественными числами везде, где не нужна очень высокая точность.
| Знак | ||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Порядок (8 бит) | Мантисса (23+1 бита) | |||||||||||||||||||||||||||||||
| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1, | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 30 | 23 | 22 | 0 | |||||||||||||||||||||||||||||
Порядок записан со сдвигом [math]-127[/math] .
Число двойной точности (Binary64, Double precision, double)
Число́ двойно́й то́чности — компьютерный формат представления чисел, занимающий в памяти два машинных слова (в случае 32-битного компьютера — [math]64[/math] бита или [math]8[/math] байт). Часто используется благодаря своей неплохой точности, даже несмотря на двойной расход памяти и сетевого трафика относительно чисел одинарной точности.
| Знак | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Порядок (11 бит) |
Мантисса (52+1 бит) |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1, | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 62 | 52 | 51 | 0 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Порядок записан со сдвигом [math]-1023[/math] .
Число четверной точности (Binary128, Quadruple precision)
Число́ четверно́й то́чности — компьютерный формат представления чисел, занимающий в памяти четыре машинных слова (в случае 32-битного компьютера — [math]128[/math] бит или [math]16[/math] байт). Используется в случае необходимости крайне высокой точности.
| Знак | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Порядок (15 бит) |
Мантисса (112+1 бит) |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1, | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 126 | 112 | 111 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Мантисса (112+1 бит) |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 0 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Порядок записан со сдвигом [math]-16383[/math] .
Обычно этот формат реализуется программно, случаи аппаратной реализации крайне редки. Также не гарантируется поддержка этого типа в языках программирования, хотя кое-где она и реализована (например, компилятор gcc для архитектуры x86 позволяет использовать тип __float128, являющийся программной реализацией числа с четверной точностью). В совокупности эти факторы делают Quadruple весьма экзотичным и редко встречающимся форматом чисел с плавающей запятой.
Диапазон значений чисел с плавающей запятой
Диапазон чисел, которые можно записать данным способом, зависит от количества бит, отведённых для представления мантиссы и показателя. Пара значений показателя (когда все разряды нули и когда все разряды единицы) зарезервирована для обеспечения возможности представления специальных чисел. К ним относятся ноль, значения NaN (Not a Number, «не число», получается как результат операций типа деления нуля на ноль) и [math]\pm\infty[/math] .
Данная таблица только лишь примерно указывает границы допустимых значений, без учета возрастающей погрешности с ростом абсолютного значения и существования денормализованных чисел.
| Название в IEEE 754 | Название типа переменной в Си | Диапазон значений | Бит в мантиссе | Бит на переменную |
|---|---|---|---|---|
| Half precision | — | 6,10×10 -5 ..65504 | 11 | 16 |
| Single presicion | float | -3,4×10 38 ..3,4×10 38 | 23 | 32 |
| Double precision | double | -1,7×10 308 ..1,7×10 308 | 53 | 64 |
| Extended precision | На некоторых архитектурах (например в сопроцессоре Intel) long double | -3,4×10 4932 ..3,4×10 4932 | 65 | 80 |
Особые значения чисел с плавающей точкой
Ноль (со знаком)
Как уже было оговорено выше, в нормализованной форме числа с плавающей точкой невозможно представить ноль. Поэтому для его представления зарезервированы специальные значения мантиссы и порядка — число считается нулём, если все его биты, кроме знакового, равны нулю. При этом в зависимости от значения бита знака ноль может быть как положительным, так и отрицательным.
| Знак | |||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Порядок | Мантисса | ||||||||||||||||
| 0 /1 | 0 | 0 | 0 | 0 | 0 | 1, | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | = [math]\pm0[/math] |
| 14 | 10 | 9 | 0 | ||||||||||||||
Арифметика нуля со знаком
Арифметика отрицательного нуля аналогична таковой для любого отрицательного числа и понятна интуитивно. Вот несколько примеров:
- [math]\frac< \left| x \right| >= -0\,\![/math] (если [math]x\ne0[/math] )
- [math](-0) \cdot (-0) = +0\,\![/math]
- [math]\left| x \right| \cdot (-0) = -0\,\![/math]
- [math]x + (\pm 0) = x\,\![/math]
- [math](-0) + (-0) = -0\,\![/math]
- [math](+0) + (+0) = +0\,\![/math]
- [math]\frac<-\infty>= +0\,\![/math]
- [math]\frac<\left|x\right|>= -\infty\,\![/math] (если [math]x\ne0[/math] )
Неопределенность (NaN)
NaN — это аббревиатура от фразы «not a number«. NaN является результатом арифметических операций, если во время их выполнения произошла ошибка (примеры см. ниже). В IEEE 754 NaN представлен как число, в котором все двоичные разряды порядка — единицы, а мантисса не нулевая.
| Знак | |||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Порядок | Мантисса | ||||||||||||||||
| 0 /1 | 1 | 1 | 1 | 1 | 1 | 1, | 0 /1 | 0 /1 | 0 /1 | 0 /1 | 0 /1 | 0 /1 | 0 /1 | 0 /1 | 0 /1 | 0 /1 | = [math]NaN[/math] |
| 14 | 10 | 9 | 0 | ||||||||||||||
Любая операция с NaN возвращает NaN. При желании в мантиссу можно записывать информацию, которую программа сможет интерпретировать. Стандартом это не оговорено и мантисса чаще всего игнорируется.
Как можно получить NaN?
- [math]\infty+(-\infty)= NaN[/math]
- [math]0\times\infty= NaN[/math]
- [math]\frac<\pm0><\pm0>= NaN[/math]
- [math]\frac<\pm\infty><\pm\infty>= NaN[/math]
- [math]\sqrt = NaN[/math] , где [math]x\lt 0[/math]
Есть и другие способы получения NaN, подробности можно найти по ссылкам в соответствующем разделе.
По определению NaN ≠ NaN, поэтому, для проверки значения переменной нужно просто сравнить ее с собой.
Бесконечности
В число с плавающей запятой можно записать значение [math]+\infty[/math] или [math]-\infty[/math] . Как и нули со знаком, бесконечности позволяют получить хотя бы близкий к правильному результат вычисления в случае переполнения. Согласно стандарту IEEE 754 число с плавающей запятой считается равным бесконечности, если все двоичные разряды его порядка — единицы, а мантисса равна нулю. Знак бесконечности определяется знаковым битом числа.
| Знак | |||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Порядок | Мантисса | ||||||||||||||||
| 0 /1 | 1 | 1 | 1 | 1 | 1 | 1, | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | = [math]\pm\infty[/math] |
| 14 | 10 | 9 | 0 | ||||||||||||||
Получить бесконечность можно при переполнении и при делении ненулевого числа на ноль. При этом [math] \frac [/math] [math]= \begin +\infty,&\text\\ NaN,&\text\\ -\infty,&\text \end [/math]
Денормализованные числа
Денормализованные числа (англ. denormalized/subnormal numbers) — это способ увеличить количество представимых числом с плавающей запятой значений около нуля, дабы повысить точность вычислений. Каждое значение денормализованного числа меньше самого маленького нормализованного («обычного») значения числа с плавающей запятой. Согласно стандарту, если порядок равен своему минимальному значению (все его биты — нули, а истинное значение порядка равно его сдвигу) и все биты мантиссы равны нулю, то это [math]\pm0[/math] . Если же мантисса не равна нулю, то это число с порядком, на единицу большим минимального (все биты порядка, кроме младшего — нули) и данной мантиссой, целая часть которой считается равной нулю, а не единице.
То есть число с плавающей запятой, при учете вышесказанного, можно задать следующим образом:
- [math](-1)^s\times1,M\times2^E[/math] , если [math]E_ \le E \le E_[/math] (нормализованное число)
- [math](-1)^s\times0,M\times2^
[/math] , если [math]E=E_-1[/math] (денормализованное число)
Где [math]s[/math] — бит знака, [math]M[/math] — последовательность битов мантиссы, [math]E[/math] — значение порядка (с учетом сдвига), [math]E_[/math] — минимальное значение порядка, используемое для записи чисел (1 — сдвиг) , [math]E_-1[/math] — минимальное значение порядка, которое он в принципе может принять (все биты нули, 0 — сдвиг).
Хоть денормализованные числа и позволяют бороться с погрешностями и обрабатывать очень маленькие значения, за эти возможности приходится дорого платить. Ввиду сложности денормализованные числа крайне редко реализуют на аппаратном уровне — вместо этого используются программные реализации, работающие значительно медленнее.
В современных процессорах обработка денормализованных чисел происходит в десятки раз медленнее, чем обработка нормализованных чисел. Ниже приведена часть таблицы из статьи Isaac Dooley, Laxmikant Kale «Quantifying the Interference Caused by Subnormal Floating-Point Values» [1]
| Производитель | Процессор | Замедление (разы) |
|---|---|---|
| IBM | PowerPC 970 | 2,4 |
| AMD | Athlon | 6,0 |
| Intel | Pentium 3 | 15,8 |
| AMD | Athlon 64 | 21,4 |
| AMD | Opteron64 | 23,8 |
| Intel | Core Duo | 44,2 |
| Intel | P4 Xeon | 97,9 |
| Intel | Pentium 4 | 131,0 |
| Intel | Itanium 2 | 183,2 |
| Sun | UltraSPARC IV | 520,0 |
В таблице приведены наихудшие результаты тестирования среди всех использованных компиляторов (gcc, icc, xlc) со всеми доступными флагами оптимизации. Исследователи утверждают, что различие среднего случая с худшим незначительно.
Поскольку в стандартных форматах (одинарной и двойной точности) денормализованные числа получаются действительно очень маленькими и практически никак не влияют на результат некоторых вычислений (при этом заметно замедляя их скорость), то иногда они просто игнорируются. При этом используются два простых механизма, получивших называние Flush-to-zero (FTZ) и Denormals-are-zero (DAZ). Первый механизм заставляет операции возвращать ноль, как только становится ясно, что результат будет денормализованным. Второй механизм заставляет операции рассматривать поступающие на вход денормализованные числа как нули.
Ярким примером подобного «отсечения» денормализованных чисел могут послужить видеокарты, в которых резкое падение скорости вычислений в сотню раз недопустимо. Так же, например, в областях, связанных с обработкой звука, нет нужды в очень маленьких числах, поскольку они представляют столь тихий звук, что его не способно воспринять человеческое ухо.
В версии стандарта IEEE 754-2008 денормализованные числа (denormal или denormalized numbers) были переименованы в subnormal numbers, то есть в числа, меньшие «нормальных». Поэтому их иногда еще называют «субнормальными«.
Действия с числами с плавающей запятой
Умножение и деление
Самыми простыми для восприятия арифметическими операциями над числами с плавающей запятой являются умножение и деление. Для того, чтобы умножить два вещественных числа в нормализованной форме необходимо перемножить их мантиссы, сложить порядки, округлить и нормализовать полученное число.
Соответственно, чтобы произвести деление нужно разделить мантиссу делимого на мантиссу делителя и вычесть из порядка делимого порядок делителя. Затем точно так же округлить мантиссу результата и привести его к нормализованной форме.
Сложение и вычитание
Идея метода сложения и вычитания чисел с плавающей точкой заключается в приведении их к одному порядку. Сначала выбирается оптимальный порядок, затем мантиссы обоих чисел представляются в соответствии с новым порядком, затем над ними производится сложение/вычитание, мантисса результата округляется и, если нужно, результат приводится к нормализированной форме. Пример:
Выполним сложение чисел с плавающей точкой и смещенным порядком в 32-х разрядном формате и . Переведем в машинный вид. Для этого сначала переведем его в двоичную систему счисления.
Нормализуем полученное двоичное число по правилам машинной арифметики.
Найдем смещенный порядок. Так как в условии говорится о 32-разрядном представлении, то смещение порядка равно .
Число отрицательное, следовательно, в бите знака будет стоять единица.
Итак, первое число в машинном 32-разрядном представлении с плавающей точкой будет иметь вид: 10000111 (жирным шрифтом выделен порядок числа, длина мантиссы — 23 бита).
Переведем второе число в машинный вид, совершая те же действия.
= ,. . В качестве мантиссы будут сохранены первые бита после запятой т.е. . Очевидно, что порядок со смещением у второго числа будет таким же, как и у первого.
Второе число положительное, следовательно, бит знака будет содержать ноль.
Итак в машинном 32-разрядном представлении второе число будет иметь вид:
10000111 Далее в арифметических операциях будет использоваться число ,=, а не = видимо для упрощения(хотя это не совсем корректно).
Порядки у слагаемых равны, поэтому пропускаем шаг выравнивания порядков и проводим вычитание мантисс по правилам двоичной арифметики. В компьютере этим занимается арифметический сопроцессор, встроенный в центральный процессор машины.
,
Приводим полученный результат к машинному виду. Для этого мы должны внести поправку в порядок — уменьшить его на единицу. Знак результата — положительный, следовательно, бит знака содержит ноль.
10000110
Проверим правильность наших вычислений. Переведем результат в десятичное представление.
Найдем реальный порядок результата, вычтя из него значение смещения .
Следовательно, число результата будет иметь вид: ,
Результат наших вычислений верен, так как - .
Алгоритм получения представления вещественного числа в памяти ЭВМ
Покажем преобразование действительного числа для представления его в памяти ЭВМ на примере величины типа Double.
Как видно из таблицы, величина этого типа занимает в памяти [math]8[/math] байт. На рисунке ниже показано, как здесь представлены поля мантиссы и порядка (нумерация битов осуществляется справа налево):
| Знак | Смещённый порядок | Мантисса |
|---|---|---|
| 63 | 62..52 | 51..0 |
Можно заметить, что старший бит, отведенный под мантиссу, имеет номер [math]51[/math] , т.е. мантисса занимает младшие [math]52[/math] бита. Черта указывает здесь на положение двоичной запятой. Перед запятой должен стоять бит целой части мантиссы, но поскольку она всегда равна [math]1[/math] , здесь данный бит не требуется и соответствующий разряд отсутствует в памяти (но он подразумевается). Значение порядка хранится здесь не как целое число, представленное в дополнительном коде. Для упрощения вычислений и сравнения действительных чисел значение порядка в ЭВМ хранится в виде смещенного числа, т.е. к настоящему значению порядка перед записью его в память прибавляется смещение. Смещение выбирается так, чтобы минимальному значению порядка соответствовал нуль. Например, для типа Double порядок занимает [math]11[/math] бит и имеет диапазон от [math]2[/math] [math]-1023[/math] до [math]2[/math] [math]1023[/math] , поэтому смещение равно [math]1023[/math] ( [math]10[/math] ) [math]=[/math] [math]1111111111[/math] ( [math]2[/math] ). Наконец, бит с номером [math]63[/math] указывает на знак числа.
Таким образом, из вышесказанного вытекает следующий алгоритм для получения представления действительного числа в памяти ЭВМ:
- перевести модуль данного числа в двоичную систему счисления;
- нормализовать двоичное число, т.е. записать в виде M [math] \times [/math] 2 p , где M — мантисса (ее целая часть равна [math]1[/math] ( [math]2[/math] )) и p — порядок, записанный в десятичной системе счисления;
- прибавить к порядку смещение и перевести смещенный порядок в двоичную систему счисления;
- учитывая знак заданного числа (0 — положительное; 1 — отрицательное), выписать его представление в памяти ЭВМ.
Пример. Запишем код числа [math]-312[/math] , [math]3125[/math] .
- Двоичная запись модуля этого числа имеет вид [math]1001110000101[/math] .
- Имеем [math]1001110000101[/math] [math]=[/math] [math]1001110000101[/math] [math]\times[/math] [math]2[/math] [math]8[/math] .
- Получаем смещенный порядок [math]8[/math] [math]+[/math] [math]1023[/math] [math]=[/math] [math]1031[/math] . Далее имеем [math]1031[/math] ( [math]10[/math] ) [math]=[/math] [math]10000000111[/math] ( [math]2[/math] ).
- Окончательно
| 1 | 10000000111 | 0011100001010000000000000000000000000000000000000000 |
| 63 | 62..52 | 51..0 |
Очевидно, что более компактно полученный код стоит записать следующим образом: C073850000000000(16).
Другой пример иллюстрирует обратный переход от кода действительного числа к самому числу.
Пример. Пусть дан код 3FEC600000000000(16) или
| 0 | 01111111110 | 1100011000000000000000000000000000000000000000000000 |
| 63 | 62..52 | 51..0 |