tags:

views:

203

answers:

3

When adding the digits of a number in PowerShell, all is well with integers that have a length -le 29.

$largeInteger = 11111111111111111111111111111 #29 digits sums correctly
$sumDigits = 0
$largeInteger
while ($largeInteger -ne 0)
{
    $sumDigits += $largeInteger  % 10
    $largeInteger  = [MATH]::Floor($largeInteger /10) 
}

$sumDigits

Things get interesting when the length of the number -gt 29. In the case where the length is 30, the sum = 77.

Any ideas?

A: 

Changing largeInteger from 29 1's to 30 1's changes the type of the variable from Decimal to Double. Use $largeInteger.GetType() to see that.

The math in the algorithm does not work so fine on doubles. Run the 2 lines in the loop repeatedly on the prompt to see the values in each step.

Once largeInteger goes from decimal to double, the arithmetic is not precise any more. That is why I suggested runnning the 2 lines on the prompt.

Here is the output -
PS C:> $largeInteger % [double]10
8
PS C:> $largeInteger % [double]100
88
PS C:> $largeInteger % [double]1000000000000000000
1.11105501764518E+17
PS C:> $largeInteger % [double]1000000000000000000000
1.11111105501765E+20
PS C:> $largeInteger % [double]1000000000000000000000000000
1.11111111111104E+26
PS C:> $largeInteger % [double]100000000000000000000000000000
1.11111111111111E+28
PS C:> $largeInteger % [double]1000000000000000000000000000000
1.11111111111111E+29

You can see the distortion that occurs due to the internal imprecise representation of the double which cannot be accurately represented in binary. As the divisor increases the accuracy of the increasing remainder also improves.

Mohit Chakraborty
Yep - aware of the data type change, that still doesn't explain the behaviour though.
stahler
I have expanded the answer and added o/p from the prompt to clarify.
Mohit Chakraborty
A: 

You have an over flown double that is being handled as a special case by Powershell. You might try $largeInteger = [float]111111111111111111111111111111. You will still lose some precision using a float.

For more information, see float (C# Reference)

Dustin Venegas
+2  A: 

You will have to install a bignum library. There are some pointers here. Either that or use a platform that has bignums built in.

dangph
Cool - will check this out.
stahler