In PowerShell floating-point literals are of type [double]
, and the closest to 19.025 in double precision is 19.0249999999999985789... which is closer to 19.02 than 19.03. Therefore the result is as expected.
In fact most decimal values won't be stored exactly in binary floating-point. If you're not aware of that please check out Is floating point math broken?. It's impossible to store your values as finite non-repeating binary fractional values. You can check that easily by printing more digits
PS $> 11.025, 12.025, 19.015, 19.025, 29.025, 39.025 |% { $_.ToString("G60") }
11.0250000000000003552713678800500929355621337890625
12.0250000000000003552713678800500929355621337890625
19.0150000000000005684341886080801486968994140625
19.02499999999999857891452847979962825775146484375
29.02499999999999857891452847979962825775146484375
39.02499999999999857891452847979962825775146484375
There is nothing that prevents midpoint rounding from working, it's just because the digit isn't exactly 5. If you want to deal with exact decimal values you must use the [decimal]
type. But you'll have to initialize the value directly with the d
suffix (like 19.025d
) or convert from string as [decimal]"19.025"
. Don't cast from [double]
to [decimal]
because that won't give you the lost precision back, [decimal]double_literal
is done as [decimal]([double]double_literal)
. [decimal]19.025
can result in the value rounded to [double]
which is 19.0249999999999985789... Somehow it works in that case, probably because the shell constructs the [decimal]
directly from the literal as string, but it won't work in all cases, for example
PS $> [decimal]19.0255555555555555555555555555
19.0255555555556
PS $> [decimal]19.02555555555555e25
190255555555556000000000000