0

I need a single variable which can store a 128-bit, unsigned integer. The largest type that Powershell recognizes, however, is UInt64. Is it possible to define a UInt128, or even UInt256 variable?

For context, I'm using Powershell 7.2.0.

martorad
  • 165
  • 1
  • 12
  • 3
    PowerShell is limited to what .NET supports. There is no direct support for arbitrary fixed-size integers, but there is `BigInteger` for arbitrary-precision arithmetic. If you really need a specific length you would need to verify it doesn't exceed 128 bits yourself (`.GetBitLength()`). (Of course, it *is* possible to implement 128-bit or 256-bit math using smaller types, by handling carry and overflow, but this is exceedingly clunky to do in a language like PowerShell, with no support for operator overloading.) – Jeroen Mostert Nov 23 '21 at 14:16
  • 2
    Can you describe the use case a little further? As Jeroen mentions, you can compose a new type from existing ones - which may or may not fit your use case, chiefly depending on how performance-sensitive your code is – Mathias R. Jessen Nov 23 '21 at 15:16
  • Well this doesn't really have a practical use, I'm just making a script for fun. I want to find prime numbers within the Fibonacci sequence, which is why I need such a large integer size. And while Jeroen's answer works, most Powershell functions, especially those in `[Math]`, aren't made for BigInteger. I see now that a scripting language may not be the best bet for a use case such as this :) – martorad Nov 24 '21 at 07:52

1 Answers1

2

From your comments:

I want to find prime numbers within the Fibonacci sequence, which is why I need such a large integer size

For this, [bigint] (type accelerator for the System.Numerics.BigInteger type) is what you want - it doesn't have any upper boundary and is designed specifically for doing integer aritmetic with large values - exactly the kind of thing you need when hunting for primes!

[...] most Powershell functions, especially those in [Math], aren't made for BigInteger.

The good news is the [bigint] brings its own!

Here's how you could implement a simple (and slow) recursive Fibonacci generator with [bigint]:

function Get-FibonacciTerm {
  param(
    [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
    [int]$N
  )

  process {
    if($N -lt 1){ return [bigint]::Zero }
    if($N -lt 3){ return [bigint]::One }

    return (Get-FibonacciTerm -N ($N-1)) + (Get-FibonacciTerm -N ($N-2))
  }
}
PS ~> 1..12 |Get-FibonacciTerm
1
1
2
3
5
8
13
21
34
55
89
144

As you might have noticed, basic arithmetic operators like + is overloaded by [bigint] and therefore works exactly as you'd expect "out of the box".

In addition, [bigint] provides a set of static helper methods to provide cognates to most of the static [math] functions. Here's a simple (and again, fairly slow/inefficient) Prime generator/tester using some of them:

function Get-PrimeNumber {
  param(
    [bigint]$Below = 1000
  )

  for($i = [bigint]::Zero; $i -lt $Below; $i = [bigint]::Add($i, [bigint]::One)){
    if($i -le 1){ continue }
    if([bigint]::Remainder($i, 2) -eq 0){ 
      if($i -eq 2){ $i }
      continue
    }
    
    $foundFactor = $false

    for($j = 3; $j -lt $i; $j = [bigint]::Add($j, 2)){
      if([bigint]::Remainder($i, $j) -eq 0){
        $foundFactor = $true
        break
      }
    }

    if(-not $foundFactor){ $i }
  }
}
PS ~> Get-PrimeNumber -Below 100
2
3
5
7
11
13
17
19
23
29
31
37
41
43
47
53
59
61
67
71
73
79
83
89
97

Now, the first optimization you might want to make here is to only search up until the root of $i in the inner loop. This is where [bigint] starts to diverge from [math] - there's no built-in Sqrt() function!

Luckily, you can roll your own :)

In conclusion:

  • For large integer arithmetic, [bigint] is definitely your friend
  • It doesn't quite have complete feature parity with builtin integral types, but supports basic arithmetic operations

I see now that a scripting language may not be the best bet for a use case such as this

I wouldn't be so quick to dismiss the entire category of "scripting languages" - PowerShell is not necessarily a good fit for this use case, because optimization of large integer math has never been a major priority in neither PowerShell nor .NET - but there are other languages out there better suited because they've been optimized for it.

Python (>=3.x) natively supports unbounded numbers and is generally much faster for arithmetic operations than PowerShell. JavaScript also has support for a BigInt type similar to [bigint] for numbers >2^53, also surprisingly fast.

Mathias R. Jessen
  • 157,619
  • 12
  • 148
  • 206
  • Wow, this is easily the most in-depth, comprehensive answer I've ever gotten on a question here. Thank you, Mathias, you're a real Powershell prodigy. :) – martorad Nov 24 '21 at 11:29