Внутреннее представление данных
.pdfvk.com/club152685050
Внутреннее представление данных типа int
Язык C/C++ поддерживает IEEE-стандарт внутреннего представления данных типа int
Институт инженеров по электротехнике и электронике — IEEE (англ.Institute of Electrical and Electronics Engineers) (I triple E — «Ай трипл и») — международная некоммерческаяассоциация специалистов в области техники, мировой лидер в области разработки стандартов по радиоэлектронике и электротехнике.
Тип "целое" включает данные типа char, short int, long вместе со всеми их вариантами signed и unsigned.
Данные типа short int занимают 2 байта
short int
SЗначение числа
15 |
14 |
0 |
|||
unsigned short |
|
|
|||
|
|
|
|
|
|
|
|
|
Значение числа |
|
|
15 |
|
|
0 |
|
|
Данные типа long int (int) занимают 4 байта |
|||||
long int |
|
|
|||
|
S |
|
|
Значение числа |
|
31 |
30 |
0 |
|||
unsigned long int |
|
|
|||
|
|
|
|
Значение числа |
|
31 |
|
|
0 |
S – знаковый разряд числа
S=0 – число положительное
S=1 – число отрицательное
Положительные числа хранятся в памяти и вступают в операции в прямом коде, т.е. в обычном двоичном представлении числа. Отрицательные числа хранятся в памяти компьютера в дополнительном коде.
|
X10 |
= 33 |
X2 = 0 000 0000 0010 0001 |
0021h |
|
|
X10 |
= -33 |
|
|
|
0 000 0000 0010 0001 |
прямой код |
|
|||
|
1 111 1111 1101 1110 |
обратный код |
|
||
+ |
|
1 |
|
|
X2 = 1 111 1111 1101 1111 дополнительный код (FFDFh) int
01111111 11111111 |
32767 (unsigned int, signed int) |
|
11111111 11111111 (FFFFh) |
65535 unsigned |
int |
|
-1 signed int |
|
vk.com/club152685050
Внутреннее представление данных с плавающей точкой
Типы данных с плавающей точкой хранятся в памяти компьютера иначе, чем целочисленные.
С/С++ поддерживает IEEE-стандарт (IEEE 754-2008 - стандарт двоичной арифметики с плавающей точкой, краткое изложение http://www.softelectro.ru/ieee754.html, 1985 год – первая версия стандарта).
IEEE Computer Society. IEEE Standard for Floating-Point Arithmetic. IEEE Standard 754-2008, August 2008.
В соответствии с этим стандартом данные представляются в виде двух частей – мантиссы М и порядка Р числа в двоичной системе счисления.
С = М*2Р
Число бит для хранения мантиссы и порядка зависит от типа данных с плавающей точкой float
S |
|
P(8бит) |
|
|
М (23 бита) |
|
|
|
31 |
|
30 |
23 |
22 |
0 |
|
|
|
|
|
|
|
|
|
|
|
|
double |
|
|
|
|
|
|
||
|
|
|
|
|||||
S |
|
P(11бит) |
|
M (52 бита) |
|
|||
63 |
|
62 |
52 |
|
51 |
|
0 |
|
|
|
|
S – знак числа
P – сдвинутый порядок числа (порядок+смещение)
M – мантисса числа
Вещественное число хранится в памяти с нормализованной мантиссой. У нормализованной двоичной мантиссы старший бит всегда равен 1, поэтому он не хранится в памяти. Это экономит 1 бит и, следовательно, увеличивает точность представления двоичного числа. Эта единица присутствует неявно и называется неявной единицей (implicate one). Отбрасывание старшей цифры мантиссы выполняется для форматов float double, но не выполняется для long double.
Порядок числа хранится «сдвинутым», т.е. к нему прибавляется число так, чтобы порядок был всегда неотрицательный. Для чисел формата float прибавляется 127, для double 1023. Всегда неотрицательный порядок избавляет от необходимости выделять один бит для хранения знака и упрощает выполнение операций сравнения порядков и арифметических операций над ними.
Пример. Перевод десятичного вещественного числа в формат одинарной точности
1. |
Перевести вещественное число в двоичный |
1. |
X = 15,2510 = 1111,012 |
|
|||
вид. |
|
|
|
|
|
||
2. |
Нормализовать полученное двоичное число. |
2. |
1111,012 =1,11101*23 |
|
|||
3. |
Отбросить скрытую единицу. |
3. |
11101*23 |
|
|
||
4. |
Определить мантиссу в двоичном виде. |
4. M=11101 |
|
||||
5. |
Определить порядок в десятичном виде, |
|
|||||
5. p=3+127=13010=1000 00102 |
|||||||
вычислить смещенный порядок, и перевести |
|||||||
6. |
S=0 |
|
|||||
его в двоичный вид. |
|
||||||
7. |
|
0100 0001 |
0111 0100 0000 0000 0000 0000 |
||||
6. |
Определить значение старшего бита, |
|
|||||
|
4174 0000h |
23-5=18 нулей |
|||||
соответствующего знаку числа. |
|
||||||
7. |
Записать ответ |
|
|
|
|
|
vk.com/club152685050
float x,y,z; x=123456789; y=123456788; z=x-y;
cout<<"Result: "<< z<<endl;
Result=8
Если пример посчитать на бумажке, то ответ будет 1. Абсолютная ошибка равна +7. Почему ответ получился неправильным?
Число 123456789 в single=4ceb79a3 4CEB79A3hex(ieee)=123456792(dec) абсолютная ошибка представления равна +3
Число 123456788 в single=4CEB79A2hex(ieee)=123456784(dec) абсолютная ошибка представления равна -4
Относительная погрешность исходных чисел приблизительно равна 3,24e-6%
В результате одной операции относительная погрешность результата стала 800%, т.е. увеличилась в 2,5e+8 раз.
Это я называю "Опасной редукцией", т.е. катастрофическим понижением точности вычислений в операция где абсолютное значение результата много меньше любого из входного значения переменных.
На самом деле ошибки точности представления числа наиболее безобидные в компьютерных вычислениях, и обычно многие программисты на них не обращают никакого внимания. Тем не менее они вас могут сильно огорчить.