Почему PowerShell просто преобразует арифметические c целых чисел в удвоение? - PullRequest
2 голосов
/ 19 июня 2020

Я использую PowerShell в течение некоторого времени и только что наткнулся на проект PSKoan:

https://github.com/vexx32/PSKoans

На одном из самых первых коанов, которые я нашел какое-то странное поведение, я не могу себе объяснить. Коан о числовых типах пытается научить, как powershell будет динамически преобразовывать типы переменных из int в long и из int в double при определенных операциях. • 1008 :

The answers you seek...
Expected the value to have type [long] or any of its subtypes, but got 2147483648 with type [double].

Это можно сузить до следующего примера, который я не понимаю:

Почему черт возьми, теперь это двойной, а не длинный?

Я использую PS 5.1:

enter image description here

PS Здесь уже поздно, так что, возможно, я упускаю что-то действительно очевидное, я уже готов к большой ладони лица;)

1 Ответ

3 голосов
/ 19 июня 2020

Действительно, в контексте выражений (вычислений) , PowerShell действительно автоматически расширяет все, что превышает макс. значение [int] / [uint] (32-битные целые числа со знаком / без знака) или [long] / [ulong] (64-бит) до [double], что легко проверить [1] :

# Ditto for [uint], [long], [ulong]
PS> ([int]::MaxValue + 1).GetType().Name
Double # [double]

Напротив, целочисленные типы меньше [int] повышаются до [int] (System.Int32), если их макс. при вычислении превышено значение :

# Ditto for [sbyte], [int16], [uint16]
PS> ([byte]::MaxValue + 1).GetType().Name
Int32 # same as: [int]

Только с числом литералами продвижение на следующий по величине знаковый - целое число Тип встречается для значений за пределами [int]:

Примечание. Любой числовой литерал , значение которого находится между [int]::MinValue и [int]::MaxValue - даже если он может соответствовать целочисленному типу меньшего - по умолчанию [int], то есть 32-битное целое число со знаком (System.Int32).

# Note: 2147483648 is the result of ([int]::MaxValue + 1)
PS> (2147483648).GetType().Name
Int64  # same as: [long]

И если числовой литерал превышает значение [long]::MaxValue, происходит повышение до [decimal]:

# Note: 9223372036854775808 is the result of ([long]::MaxValue + 1)
PS> (9223372036854775808).GetType().Name
Decimal # [decimal]

Только если вы превысите [decimal]::MaxValue], это повышение до [double] - с его потенциалом. потеря точности - происходит:

# Note: 79228162514264337593543950336 is the result of ([decimal]::MaxValue + 1)
PS> (79228162514264337593543950336).GetType().Name
Double # [double]

Прямой вывод указанного выше значения делает преобразование в [double] сразу очевидным, поскольку при форматировании вывода используется экспоненциальная запись: 7.92281625142643E+28


[1] Любопытно, что попытка вычислить значение за пределами [decimal]::MaxValue не удается , вызывая завершение инструкции ошибка: ([decimal]::MaxValue + 1).GetType().Name

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...