Поведение PowerShell в строку
PowerShell обрабатывает следующие команды с интересными результатами. Надеюсь, что умный парень может объяснить, почему.
Здесь нет проблем:
PS C:\> [float]"4.2"
4.2
PS C:\> [double]"4.2"
4.2
Но как только вы сделаете небольшую арифметику, все станет интереснее:
PS C:\> [float]"4.2" + 3
7.19999980926514
PS C:\> [double]"4.2" + 3
7.2
2 ответа
Это как-то связано с тем, как двоичные числа с плавающей запятой ([float]
а также [double]
), представлены в памяти.
Чтобы представить числовые значения, которые варьируются в диапазоне, превышающем то, что может постоянно храниться в 32 или 64 битах памяти, числа с плавающей запятой сохраняются в виде вычисления в форме:
coefficient*base^exponent
Для 32-битного двоичного числа с плавающей точкой (что [float]
is), это позволяет с точностью примерно 7,2 десятичных знака - и действительно вы видите, что точность становится шаткой после 7 десятичных знаков в вашем первом примере.
[double]
занимает 64 бита памяти (отсюда и название double) и, следовательно, имеет гораздо более высокую точность.
В любом случае, пожалуйста, используйте [decimal]
для десятичной арифметики, поскольку она всегда использует 10 в качестве своей базы, а не 2 (что, как следует из названия, является тем, что двоичные числа с плавающей запятой используют в качестве своей основы).
[decimal]"4.2" + 3
Это вызвано двумя вариантами поведения PowerShell:
- Когда выполняется арифметика, PowerShell преобразует
float
вdouble
, - При форматировании чисел с плавающей точкой для отображения PowerShell по умолчанию использует общий формат и значения по умолчанию, которые зависят от типа (семь цифр для
float
15 дляdouble
) но подавляет конечные нули.
Чтобы понять детали, мы начнем с наблюдения, что, когда "4.2" должным образом конвертируется в базовую двоичную с плавающей точкой IEEE-754 с округлением до ближайшего, результат в точности равен 4.19999980926513671875 для float
и 4.20000000000000017763568394002504646778106689453125 для double
,
Для отображения float
В результате PowerShell (по сути) форматирует его с семью десятичными цифрами, производя "4.200000", а затем подавляет конечные нули, производя "4.2".
PowerShell делает арифметику используя double
не float
, Когда вы добавляете 3, результат double
не float
, Результирующее значение равно 7.19999980926513671875, и, так как это double
PowerShell форматирует его по умолчанию double
формат. В этом случае он форматирует его с 15 цифрами, получая "7.19999980926514".
За [double]"4.2" + 3
с другой стороны, результат 7.20000000000000017763568394002504646778106689453125. Когда это отформатировано с 15 цифрами, результат "7.20000000000000". Подавление конечных нулей оставляет "7.2".
(Обратите внимание, что такие простые результаты не всегда имеют место после арифметики. Могут быть ситуации, когда сложение вызывает некоторое округление младших битов, в результате чего вычисленный результат не будет заканчиваться конечными нулями при форматировании с 15 цифрами.)