Точность в поплавках C - PullRequest
8 голосов
/ 19 марта 2012

Обычно мы говорим, что число с плавающей точкой имеет точность 6 цифр после десятичной точки.Но если мы храним большое число порядка 10 ^ 30, мы не получим 6 цифр после десятичной точки.Так правильно ли говорить, что числа с плавающей точкой имеют точность 6 цифр после десятичной точки?

Ответы [ 4 ]

10 голосов
/ 19 марта 2012

«6 цифр после десятичной запятой» не является обязательным, и ваш пример является хорошей демонстрацией этого.

Это является точной спецификацией типа данных float.

Точность float составляет 24 бит. Есть 23 бита, обозначающих дробь после двоичной точки, плюс есть также «неявный ведущий бит», согласно онлайн-источнику. Это дает 24 значащих бита.

Следовательно, в десятичных цифрах это примерно:

24 * log (2) / log (10) = 7,22

8 голосов
/ 19 марта 2012

Звучит так, как будто вы спрашиваете о точности до десятичных знаков (цифры после десятичной точки), тогда как значащих цифр (общее количество цифр без начальных и начальных нулей)лучший способ описать точность чисел.

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


Большинство систем в наши дни используют формат с плавающей точкой IEE для представления чисел в C. Однако, если вы на что-тонеобычно, стоит проверить.Числа IEE float одинарной точности состоят из трех частей:

  • Знаковый бит (это число положительное или отрицательное)
  • (обычно такжеподпись) экспонента
  • Дробь (число перед применением показателя)

Как и следовало ожидать, все это хранится в двоичном формате.


Сколько значащих цифр?

Если вы используете числа IEE-754, «сколько значащих цифр», вероятно, не простой способ думать об этом, потому что точность измеряется в двоичной значащейцифры, а не десятичные .float s имеют только 23 бита точности для дробной части, но поскольку существует неявный начальный бит (если только дробная часть не является всеми нулями, что указывает на конечное значение 1), существует 24 эффективных бита точности.

Это означает, что есть 24 значащие двоичные цифры , что не переводит в точное число десятичных значащих цифр.Вы можете использовать формулу 24 * log (2) / log (10), чтобы определить, что есть 7,225 цифр десятичной точности, что не очень хороший ответ на ваш вопрос, поскольку есть числа из 24 значащих двоичных цифр, которые толькоиметь 6 значащих десятичных цифр.

Итак, числа с плавающей запятой одинарной точности имеют 6-9 значащих десятичных знаков точности , в зависимости от числа.

Интересно, что эту точность можно использовать и для работынаибольшее целое число подряд (считая от нуля), которое вы можете успешно представить в виде числа с плавающей запятой одинарной точностиЭто 2 ^ 24, или 16 777 216.Вы можете точно хранить большие целые числа, но только если они могут быть представлены в 24 значащих двоичных разрядах.


Дополнительные сведения: ограниченный размер компонента дроби - это то же самое, что вызывает это в Javascript:

> console.log(9999999999999999);
10000000000000000

Числа Javascript всегда представлены как числа с плавающей запятой двойной точности, которые имеют точность 53 бита.Это означает, что между 2 ^ 53 и 2 ^ 54 могут быть представлены только четные числа, поскольку последний бит любого нечетного числа теряется.

6 голосов
/ 19 марта 2012

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

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

IEEE754 указывает, что число с плавающей запятой находится в научная запись : (-1) с × 2 е × м
где s имеет ширину один бит, e имеет ширину восемь бит, а m имеет ширину двадцать три бита.Математически, m имеет ширину 24 бита, потому что всегда предполагается, что старший бит равен 1.

Итак, максимальное количество десятичных цифр, которое может быть аппроксимировано этим представлением, равно: log 10 (2 24 ) = 7,22 .Это приблизительно семь значащих десятичных цифр и показатель степени в диапазоне от 2 -126 до 2 127 .

Обратите внимание, что показатель степени измеряется отдельно.Это точно так же, как если бы вы использовали обычные научные обозначения , например: «Человек весит 72,3 кг = 7,23 × 10 4 грамм».Обратите внимание, что здесь есть три значащих цифры , что означает, что число является точным с точностью до 100 граммов.Но есть также показатель , который является совершенно другим числом.Вы можете иметь очень большой показатель степени с очень небольшим количеством значащих цифр, например, «Солнце весит 1,99 × 10 33 грамм».Большое число, несколько цифр.

3 голосов
/ 19 марта 2012

В двух словах, число с плавающей запятой может хранить около 7-8 значащих десятичных цифр . Позвольте мне проиллюстрировать это на примере:

1234567001.00
         ^
         +---------------- this information is lost

.01234567001
           ^ 
           +-------------- this information is lost

По сути, в плавающем запоминается два значения: 1234567 и позиция десятичной точки.

Теперь это упрощенный пример. Floats хранит двоичные значения вместо десятичных значений. 32-разрядный IEEE 754 с плавающей запятой имеет место для 23 "значащих битов" (плюс первый, который всегда считается равным 1), что соответствует примерно 7-8 десятичным цифрам.

 1234567001.00 (dec) =

 1001001100101011111111101011001.00 (bin)  gets rounded to

 1001001100101011111111110000000.00 =
  |    23 bits           |

 1234567040.00 (dec)

И это именно то, что производит C:

void main() {
    float a = 1234567001;
    printf("%f", a);      // outputs 1234567040
}
...