Bartosz Kacprzak
Bartosz Kacprzak

Reputation: 13

How can I define rounded variable in Powershell?

I'm writing short powershell to fill contract in htm file. I have a problem in definig rounded up variables $FirstFee and $SecondFee.

The script is :

$InvoiceValue = Read-Host -Prompt 'Write invoice value'
$FirstFee = [int]$InvoiceValue*0.023+40
$SecondFee = [int]$InvoiceValue*0.023+60

The result is presented i.ex 1234*0.23+40=323,82 instead od 324.

Where do I make a mistake?

I the next step I replace the result of rounded $FirstFee and $SecondFee in a RTF file, but the values must be rounded.

Upvotes: 1

Views: 135

Answers (1)

mklement0
mklement0

Reputation: 438093

tl;dr:

You need two casts, one for $InvoiceValue, and another for the result of the calculation.

$FirstFee = [int] ([int] $InvoiceValue * 0.023 + 40)

Alternatively, type-constrain the receiving variable (place the cast to the left of the variable name in the assignment), which has the same effect (while also coercing any values assigned in the future to [int]:

[int] $FirstFee = [int] $InvoiceValue * 0.023 + 40

Note that an [int] cast performs half-to-even rounding, so that both [int] 1.5 and [int] 2.5 return 2. To control the rounding behavior, use [Math]::Round() - see this answer.


Background information:

  • PowerShell casts - such as [int] - have high precedence in PowerShell, so that [int] $InvoiceValue * 0.023 + 40 is the same as: ([int] $InvoiceValue) * 0.023 + 40

  • PowerShell performs many automatic type conversions; in a numeric context, mismatched operand types cause the other operand to be automatically promoted to the larger among the operand types - and if the result doesn't fit into that type, PowerShell automatically switches to [double][1].

In the following example, the result is of type [double] because [double] is larger than [int].

# Note: The [int] cast isn't strictly necessary here.
#       PowerShell defaults to [int] for integer number literals, if small enough.
([int] 1 * 0.5).GetType().Name # -> Double

Therefore, in order to force the result to be an [int] again, another [int] cast is needed around the entire calculation.


[1] This behavior is somewhat unfortunate, because for integer types it would be preferable to switch to a large integer type (e.g., [long]) rather than [double], because using [double] for very large integers results in loss of accuracy. It is only in PowerShell number literals, that the preferable behavior is applied; e.g.: (2147483648).GetType().Name indicates [long] - PowerShell automatically chose [long], because the number can no longer fit in an [int] (its value is [int]::MaxValue + 1); by contrast, arriving at the equivalent number by calculation results in the undesirable to-[double] promotion: ([int]::MaxValue + 1).GetType().Name reports [double].

Upvotes: 1

Related Questions