Как хранится число с плавающей запятой? Когда это имеет значение? - PullRequest
35 голосов
/ 11 сентября 2008

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

Как хранятся числа с плавающей запятой?

Существует ли общий стандарт для разных размеров?

На какие ошибки мне нужно обращать внимание, если я использую число с плавающей запятой?

Совместимы ли они между языками (т.е. с какими преобразованиями мне нужно иметь дело, чтобы отправить число с плавающей запятой из программы на Python в программу на C по TCP / IP)?

-Adam

Ответы [ 10 ]

24 голосов
/ 11 сентября 2008

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

Теперь вот несколько распространенных ошибок:

  • Самое большое, что вы почти никогда не хотите сравнивать два числа с плавающей запятой на равенство (или неравенство). Вместо этого вы захотите использовать сравнение больше / меньше чем.
  • Чем больше операций вы выполняете с числом с плавающей запятой, тем более значительными могут быть ошибки округления.
  • Точность ограничена размером дроби, поэтому вы не сможете правильно добавить числа, разделенные на несколько порядков. (Например, вы не сможете добавить 1E-30 к 1E30.)
12 голосов
/ 11 сентября 2008

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

5 голосов
/ 11 сентября 2008

Что касается второй части вашего вопроса, если производительность и эффективность не важны для вашего проекта, тогда я предлагаю вам передавать данные с плавающей запятой в виде строки по TCP / IP. Это позволяет избежать проблем, таких как выравнивание байтов, и упростит отладку.

5 голосов
/ 11 сентября 2008

Стандарт IEEE 754 .

Конечно, существуют и другие способы хранения чисел, когда IEE754 недостаточно хорош. Библиотеки, такие как Java BigDecimal, доступны для большинства платформ и хорошо соответствуют числовому типу SQL. Символы могут использоваться для иррациональных чисел, а соотношения, которые не могут быть точно представлены в двоичной или десятичной форме с плавающей запятой, могут быть сохранены как отношение.

3 голосов
/ 08 декабря 2009

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

Correct.

Как хранятся числа с плавающей запятой? Существует ли общий стандарт для разных размеров?

Как уже упоминалось в других постерах, почти исключительно IEEE754 и его преемник IEEE754R. Поиск в Google дает вам тысячи объяснений вместе с бит-паттернами и их объяснениями. Если у вас все еще есть проблемы с его получением, есть еще два распространенных формата FP: IBM и DEC-VAX. Для некоторых эзотерических машин и компиляторов (BlitzBasic, TurboPascal) есть несколько нечетные форматы.

На какие ошибки мне нужно обращать внимание, если я использую число с плавающей запятой? Совместимы ли они между языками (т. Е. С какими конверсиями мне нужно работать, чтобы отправить число с плавающей запятой из программы на Python в программу на C по TCP / IP)?

Практически нет, они совместимы между языками.

Очень редкие причуды:

  • IEEE754 определяет sNaN (сигнальные NaN) и qNaN (тихие NaN). Первые вызывают ловушку, которая заставляет процессор вызывать подпрограмму обработчика при загрузке. Последние не делают этого. Поскольку разработчики языка ненавидели возможность того, что sNaN прерывают их рабочий процесс, и их поддержка обеспечивает поддержку подпрограмм обработчика, sNaN почти всегда молча преобразуются в qNaN. Так что не полагайтесь на сырое преобразование 1: 1. Но опять же: это очень редко и происходит, только если NaNs присутствуют.

  • У вас могут быть проблемы с порядком байтов (байты в неправильном порядке), если файлы между разными компьютерами являются общими. Это легко обнаружить, потому что вы получаете NaNs для чисел.

3 голосов
/ 11 сентября 2008

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

В C ++ хорошее эмпирическое правило заключается в том, чтобы думать, что число с плавающей запятой дает вам 7 цифр точности, а двойное дает вам 15. Кроме того, если вам интересно знать, как проверять равенство, вы можете посмотреть на это тема вопроса.

2 голосов
/ 11 сентября 2008

Да, существует Стандарт IEEE для двоичной арифметики с плавающей точкой (IEEE 754)

Число разбивается на три части: знак, показатель степени и дробь при хранении в двоичном виде.

2 голосов
/ 11 сентября 2008

Эта статья , озаглавленная «Стандартные числа IEEE 754 с плавающей запятой», может оказаться полезной. Если честно, я не совсем уверен, что понимаю ваш вопрос, поэтому я не уверен, что это будет полезно, но я надеюсь, что это будет.

1 голос
/ 11 сентября 2008

Если вы действительно беспокоитесь об ошибках округления с плавающей запятой, большинство языков предлагают типы данных, в которых нет ошибок с плавающей запятой. SQL Server имеет типы данных Decimal и Money. .Net имеет тип данных Decimal. Они не имеют бесконечной точности, как BigDecimal в Java, но они точны вплоть до количества десятичных точек, для которых они определены. Таким образом, вам не нужно беспокоиться о долларовом значении, которое вы вводите как 4,58 долл., И сохраняются в виде значения с плавающей запятой 4,579999999999997

0 голосов
/ 11 сентября 2008

То, что я помню, это то, что 32-битное значение с плавающей запятой сохраняется с использованием 24 битов для фактического числа, а оставшиеся 8 бит используются как степень 10, определяющая, где находится десятичная точка.

Я немного заржавел по этому вопросу, хотя ...

...