Поведение 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:

Чтобы понять детали, мы начнем с наблюдения, что, когда "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 цифрами.)

Другие вопросы по тегам