Целые числа и точность с плавающей запятой
-
19-09-2019 - |
Вопрос
Это скорее численный анализ, чем вопрос программирования, но я полагаю, что некоторые из вас смогут на него ответить.
В сумме двух чисел с плавающей запятой теряется ли точность?Почему?
Потеряна ли точность в сумме чисел с плавающей запятой и целого числа?Почему?
Спасибо.
Решение
В сумме два поплавка, есть ли утраченная точность?
Если оба поплавка имеют разные величины, и оба используют полный диапазон точности (из около 7 десятичных цифр), то да, вы увидите некоторые потери в последних местах.
Почему?
Это потому, что поплавки хранятся в форме (знак) (мантисса) × 2(показатель). Анкет Если два значения имеют разные показатели, и вы добавляете их, то меньшее значение будет уменьшено до меньших цифр в мантиссе (потому что оно должно адаптироваться к более крупному показателям):
PS> [float]([float]0.0000001 + [float]1)
1
В сумме плавания и целого числа, есть ли утраченная точность?
Да, нормальное 32-разрядное целое число способно представлять значения, которые точно не вписываются в поплавок. Поплавок все еще может хранить примерно то же самое число, но больше не точно. Конечно, это относится только к достаточно большим числам, т.е. е - дольше 24 бит.
Почему?
Поскольку Float имеет 24 бита точности, и (32-битные) целые числа имеют 32. Поплаток все равно сможет сохранить величину и большинство значительных цифр, но последние места, вероятно, могут отличаться:
PS> [float]2100000050 + [float]100
2100000100
Другие советы
Точность зависит от величины исходных чисел. В плавающей запятой компьютер представляет номер 312 внутренне в качестве научной записи:
3.12000000000 * 10 ^ 2
Десятичные места в левой стороне (мантисса) зафиксированы. Экспонент также имеет верхнюю и нижнюю границу. Это позволяет ему представлять очень большие или очень маленькие числа.
Если вы попытаетесь добавить два числа, которые одинаковы по величине, результат должен оставаться одинаковым в точности, потому что десятичная точка не должна двигаться:
312.0 + 643.0 <==>
3.12000000000 * 10 ^ 2 +
6.43000000000 * 10 ^ 2
-----------------------
9.55000000000 * 10 ^ 2
Если бы вы попытались добавить очень большое и очень маленькое число, вы потеряете точность, потому что они должен быть втиснутым в вышеупомянутый формат. Рассмотрим 312 + 1230000000000000000000000. Сначала вам нужно масштабировать меньшее число, чтобы выровнять с большим, а затем добавить:
1.23000000000 * 10 ^ 15 +
0.00000000003 * 10 ^ 15
-----------------------
1.23000000003 <-- precision lost here!
Плавающая точка может обрабатывать очень большие или очень маленькие числа. Но это не может представлять оба одновременно.
Что касается добавленных INT и удвоений, то INT сразу превращается в двойник, то применяется выше.
При добавлении двух номеров с плавающей запятой, как правило, есть некоторая ошибка. Д. Голдберг «То, что каждый компьютерный ученый должен знать о арифметике с плавающей точкой» описывает эффект и причины в подробности, а также как рассчитать верхнюю границу по ошибке и как рассуждать о точности более сложных расчетов.
При добавлении плавания в целое число, целое число сначала преобразуется в поплавок с помощью C ++, поэтому добавляются два поплавка и вводится ошибка по тем же причинам, что и выше.
Точность, доступная для float
ограничен, поэтому, конечно, всегда есть риск, что любая данная операция снижает точность.
Ответ обоих ваших вопросов - "да".
Если вы попытаетесь добавить очень большой поплавок в очень маленький, у вас будут проблемы.
Или, если вы попытаетесь добавить целое число к поплавке, где целое число использует больше битов, чем плавание, доступное для его мантиссы.
Краткий ответ: компьютер представляет собой поплавок с ограниченным количеством битов, что часто делается с Мантисса и экспонент, Таким образом, только несколько байтов используются для значительных цифр, а другие используются для представления позиции десятичной точки.
Если бы вы попытались добавить (скажем) 10^23 и 7, то он не сможет точно представлять этот результат. Аналогичный аргумент применяется при добавлении плавания и целого числа - целое число будет способствовать поплавке.
В сумме двух чисел с плавающей запятой теряется ли точность?Потеряна ли точность в сумме чисел с плавающей запятой и целого числа?Почему?
Не всегда.Если сумма представима с той точностью, которую вы запрашиваете, вы не получите никакой потери точности.
Пример:0,5 + 0,75 => нет потери точности x * 0,5 => Нет потерь точности (за исключением случаев, если x слишком мало)
В общем случае добавляются числа с плавающей запятой в несколько разных диапазонах, поэтому возникает потеря точности, которая фактически зависит от режима округления.то есть:если вы добавляете числа из совершенно разных диапазонов, ожидайте проблем с точностью.
Денормализаторы нужны для того, чтобы в крайних случаях обеспечить дополнительную точность за счет процессора.
В зависимости от того, как ваш компилятор обрабатывает вычисления с плавающей запятой, результаты могут различаться.
При строгой семантике IEEE добавление двух 32-битных чисел с плавающей запятой не должно давать большей точности, чем 32-битные.На практике для этого может потребоваться больше инструкций, поэтому не следует полагаться на точные и повторяемые результаты с плавающей запятой.
В обоих случаях да:
assert( 1E+36f + 1.0f == 1E+36f );
assert( 1E+36f + 1 == 1E+36f );
Case Float + int такой же, как Float + Float, потому что стандартное преобразование применяется к Int. В случае Float + Float это зависит от реализации, потому что реализация может выбрать дополнение с двойной точностью. Конечно, может быть некоторая потеря, когда вы храните результат.
В обоих случаях ответ «да». При добавлении int
в float
, Целое число преобразуется в представление с плавающей запятой до того, как добавление в любом случае произойдет.
Чтобы понять, почему я предлагаю вам прочитать этот драгоценный камень: Что каждый компьютерный ученый должен знать о арифметике с плавающей точкой.