Reputation: 94
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?
Upvotes: 0
Views: 1911
Reputation: 1263
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<br/>
8<br/>
PS C:\> $largeInteger % [double]100<br/>
88<br/>
PS C:\> $largeInteger % [double]1000000000000000000<br/>
1.11105501764518E+17<br/>
PS C:\> $largeInteger % [double]1000000000000000000000<br/>
1.11111105501765E+20<br/>
PS C:\> $largeInteger % [double]1000000000000000000000000000<br/>
1.11111111111104E+26<br/>
PS C:\> $largeInteger % [double]100000000000000000000000000000<br/>
1.11111111111111E+28<br/>
PS C:\> $largeInteger % [double]1000000000000000000000000000000<br/>
1.11111111111111E+29<br/>
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.
Upvotes: 0
Reputation: 16909
You will have to install a bignum library. There are some pointers here. Either that or use a platform that has bignums built in.
Upvotes: 2
Reputation: 759
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)
Upvotes: 0