Powershell bigint output differ from declared value

167 Views Asked by At

I'm porting lesspass password manager to powershell, but I'm having trouble when implementing the _consume_entropy() method, especially the Python divmod.

Reproduce

PS> [bigint]$EntropyAsInt = 99600400399777174105034830393873797761817714609490038944205586760025858632478
PS> Write-Host $EntropyAsInt
99600400399777173995117538344184441997741701018199539534149245151907290284032

Difference

99600400399777174105034830393873797761817714609490038944205586760025858632478
99600400399777173995117538344184441997741701018199539534149245151907290284032
                ^ start diverging he

Question

What's the matter here? Am I using the wrong type?

3

There are 3 best solutions below

0
On BEST ANSWER

99600400399777174105034830393873797761817714609490038944205586760025858632478 is a [Double]...

PS> 99600400399777174105034830393873797761817714609490038944205586760025858632478
9.96004003997772E+76
PS> (99600400399777174105034830393873797761817714609490038944205586760025858632478).ToString("F0")
99600400399777200000000000000000000000000000000000000000000000000000000000000
PS> (99600400399777174105034830393873797761817714609490038944205586760025858632478).GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Double                                   System.ValueType

By the time it gets cast to [BigInt] the original value is already lost. Starting with a [String] preserves it, though...

PS> [bigint]$EntropyAsInt = '99600400399777174105034830393873797761817714609490038944205586760025858632478'
PS> $EntropyAsInt
99600400399777174105034830393873797761817714609490038944205586760025858632478

See Instantiating a BigInteger Object for more information.

1
On

I can replicate the behavior, but cannot explain it. What I can do is offer you a work around. Define a variable as a [bigint], then parse your number as a string referencing the previously created variable.

[bigint]$EntropyAsInt=0
[bigint]::TryParse('99600400399777174105034830393873797761817714609490038944205586760025858632478',[ref]$EntropyAsInt)

You can then verify that $EntropyAsInt contains the number you previously specified.

0
On

Thanks to Joel on Powershell slack:

The issue is that the bigint cast doesn't take effect until after the value is parsed. It will first be parsed as a double, which in where the imprecision occurs

If you want it to retain the exact number, you need to put your literal in quotes to make it a string and have the cast itself do the parsing

[bigint]$var = "12345342827266162738883736363"

Work fine

[bigint]$EntropyAsInt = "99600400399777174105034830393873797761817714609490038944205586760025858632478"