2010-05-14 4 views
38

Узнав, как числа с плавающей запятой представлены на компьютерах, я столкнулся с термином «значение смещения», которое я не совсем понимаю.Что такое «значение смещения» чисел с плавающей запятой?

Значения смещения в числах с плавающей запятой связаны с отрицательным и положительным показателем части числа с плавающей запятой.

Значение смещения числа с плавающей запятой составляет 127, что означает, что 127 всегда добавляется к экспоненциальной части числа с плавающей запятой. Как это помогает определить, является ли показатель отрицательным или положительным или нет?

+0

Еще одно интересное чтение, связанное с этим вопросом, - это статья Википедии: https://en.wikipedia.org/wiki/IEEE_754-1985 – nbro

ответ

43

В одинарной точности с плавающей запятой вы получаете 8 бит для хранения экспоненты. Вместо того, чтобы хранить его как номер дополнения подписанного двух, было решено, что было бы проще просто добавить 127 к экспоненту (так как наименьшее, что может быть в 8-битной подписке, -127) и просто сохранить его как беззнаковое число , Если сохраненное значение больше смещения, это означает, что значение показателя положительно, если оно меньше смещения, оно отрицательное, если оно равно, оно равно нулю.

+0

Итак, в формате IEEE из-за смещения 127, если поле экспоненты является «00000000», это означает, что показатель числа -127? –

+0

@KennethWorden Нет, значение экспоненты всех нулей является специальным, а числа интерпретируются как «денормализованные» (а это включает в себя и сам). –

60

b0lt уже объяснил, как работает смещение. Возможно, вы хотели бы знать, почему почему используют здесь предвзятое представление, хотя практически все современные компьютеры используют два дополнения по существу везде (и даже машины, которые не используют два дополнения, используют свое дополнение или знак -магнность, а не смещение).

Одна из целей стандартов с плавающей точкой IEEE заключалась в том, что вы могли обрабатывать биты числа с плавающей запятой как (подписанное) целое число того же размера, и если бы вы сравнили их таким образом, значения будут сортироваться в тот же порядок, что и числа с плавающей запятой.

Если вы использовали представление в дополнительном коде для показателя, малое положительное число (то есть, с отрицательным показателем) будет выглядеть очень большой целое, потому что второй MSB будет установлен. Вместо этого вместо этого используется представление смещения, вы не сталкиваетесь с этим: меньший показатель числа чисел с плавающей запятой всегда выглядит как меньшее целое число.

FWIW, это также почему числа с плавающей запятой, как правило, расположены со знаком сначала, затем с показателем и, наконец, значащим в младших значащих битах - таким образом, вы можете принимать положительные числа с плавающей запятой, обрабатывать эти биты как целые числа, и сортировать их. Когда вы это сделаете, результат будет иметь числа с плавающей запятой в правильном порядке. Например:

#include <vector> 
#include <algorithm> 
#include <iostream> 

int main() { 
    // some arbitrary floating point values 
    std::vector<double> vals = { 1e21, 1, 2.2, 2, 123, 1.1, 0.0001, 3, 17 }; 
    std::vector<long long> ivals; 

    // Take those floating point values, and treat the bits as integers: 
    for (auto &&v : vals) 
     ivals.push_back(*reinterpret_cast<long long *>(&v)); 

    // Sort them as integers: 
    std::sort(ivals.begin(), ivals.end()); 

    // Print out both the integers and the floating point value those bits represent: 
    for (auto &&i : ivals) 
     std::cout << i << "\t(" << *reinterpret_cast<double *>(&i) << ")\n"; 
} 

Когда мы запускаем этот результат выглядит следующим образом:

4547007122018943789  (0.0001) 
4607182418800017408  (1) 
4607632778762754458  (1.1) 
4611686018427387904  (2) 
4612136378390124954  (2.2) 
4613937818241073152  (3) 
4625478292286210048  (17) 
4638355772470722560  (123) 
4921056587992461136  (1e+21) 

Как вы можете видеть, даже если мы отсортировали их как целые числа, числа с плавающей запятой, что эти биты представляют также выходят в правильном порядке.

У этого есть ограничения относительно чисел с плавающей запятой. Хотя все (не древние) компьютеры согласны с представлением положительных чисел, существуют три представления, которые (довольно недавно) использовались для подписанных чисел: знаковая величина, дополнение к одному и дополнение к двум.

Простое рассмотрение битов как целого числа, и сравнение будет отлично работать на компьютере, использующем знаковое представление величины для целых чисел. Для компьютеров, которые используют дополнение своего дополнения или два, отрицательные числа будут сортироваться в инвертированном порядке. Поскольку это все еще простое правило, довольно легко написать код, который работает с ним.Если мы изменим sort вызов выше что-то вроде этого:

std::sort(ivals.begin(), ivals.end(), 
    [](auto a, auto b) { if (a < 0.0 && b < 0.0) return b < a; return a < b; } 
); 

... это будет правильно сортировать как положительные, так и отрицательные числа. Например, вход:

std::vector<double> vals = { 1e21, 1, 2.2, 2, 123, 1.1, 0.0001, 3, 17, -0.001, -0.00101, -1e22 }; 

произведет результат:

-4287162073302051438 (-1e+22) 
-4661071411077222194 (-0.00101) 
-4661117527937406468 (-0.001) 
4547007122018943789  (0.0001) 
4607182418800017408  (1) 
4607632778762754458  (1.1) 
4611686018427387904  (2) 
4612136378390124954  (2.2) 
4613937818241073152  (3) 
4625478292286210048  (17) 
4638355772470722560  (123) 
4921056587992461136  (1e+21) 
+0

Да, я тоже хотел знать, почему. Это отвечает на это. Очень интересно. Спасибо. – mudge

+3

@JerryCoffin: +1 отличный ответ (в частности, обоснование заказа в компонентах fp number). – legends2k

+0

@JerryCoffin Я не понимаю, почему числа с плавающей запятой можно рассматривать как целые числа ... Я имею в виду, что один и тот же порядок бит будет иметь другое значение для каждого типа данных. Можете ли вы уточнить? – user1534664

13

Добавление большего количества деталей к выше ответов.

Для представления 0, infinity и NaN (Not-a-Number) в плавающей запятой IEEE решил использовать специальные значения кодировки.

  • Если все биты поля экспоненты установлены в 0, то число с плавающей запятой равно 0,0.

  • Если все биты поля экспоненты установлены равными 1, а все биты части дробей равны 0, то число с плавающей запятой равно бесконечность.

  • Если все биты поля экспоненты установлены равными 1, а все биты части дроби не равны 0, то число с плавающей запятой равно NaN.

Так, в одинарной точности мы имеем 8 бит для представления поля экспоненты и есть 2 специальные значения, поэтому мы в основном имеют 256 - 2 = 254 значения, которые могут быть представлены в показателе. Таким образом, мы можем эффективно представить в экспоненте от -126 до 127, т. Е. 254 значения (126 + 127 + 1), 1 добавлено для 0.

Смежные вопросы