dinsdag 17 april 2012

Grote getallen in PowerShell

Voor de uitdagingen in Project Euler is het nodig om grote getallen te berekenen, bijvoorbeeld voor het berekenen van probleem 16:
What is the sum of the digits of the number 21000?
Python kan dit zonder enig probleem van zichzelf, maar PowerShell heeft in principe alleen de klassieke datatypen int32, int64, double en long en trekt dat niet.

Wat nu?

BigInteger 


Zie Monkey's Den artikel Calculating a factorial with Powershell voor een truc om de BigInteger-class van F# in te laden en toch met grote getallen te rekenen. Volgens het FatBeard's Adventure is er een manier om dat in PowerShell te gebruiken. Je kon F# downloaden van Microsoft om aan de benodigde libraries te komen. Maar helaas schijnt dat niet meer te werken sinds nieuwere versies van .NET . Het artikel van Monkey's Den vervolgt met de oplossing. Sinds v4 is er BigInt-ondersteuning in .NET ingebouwd. Een code-snippet :

Add-Type -Path "C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.Numerics.dll"
function factorial {
    [cmdletbinding()]
    param($x)
    if ($x -lt 1) {
        return "Has to be on a positive integer"
    }
    if ($x -eq 1) {
        $x
    } else {
        $y =  factorial ($x-1)
        [System.Numerics.BigInteger]::Multiply($x , $y)
    }
}

Op een 64-bit Windows zou de eerste regel moeten worden aangepast afhankelijk of je in 64-bit of 32-bit PowerShell werkt. Voor 64-bit PowerShell wordt dit als volgt:

Add-Type -Path "C:\Windows\Microsoft.NET\Framework64\v4.0.30319\System.Numerics.dll"

Maar hier krijg ik een foutmelding.

Add-Type : Kan bestand of assembly  file:///C:\Windows\Microsoft.NET\Framework64\v4.0.30319\System.Numerics.dll of een van de afhankelijkheden hiervan niet laden. Deze assembly is gebouwd door een runtime die nieuwer is dan de momenteel geladen runtime, en kan niet worden geladen. 
At line:1 char:9 
+ Add-Type <<<< -Path "C:\Windows\Microsoft.NET\Framework64\v4.0.30319\System.Numerics.dll" 
    + CategoryInfo : NotSpecified: (:) [Add-Type], BadImageFormatException 
    + FullyQualifiedErrorId : System.BadImageFormatException,Microsoft.PowerShell.Commands.AddTypeCommand 

Eens probleren of moet ik verder zoeken. In Doug Finke's Blog lees ik hoe ik de F# Powerpack kan installeren en hoe ik vervolgens .NET aanpas zodat het een andere runtime gebruikt. De foutmelding hierboven verwijst ook naar een andere runtime. In Under the stairs wordt uiteindelijk uitgelegd hoe je PowerShell een latere versie van de CLR kunt laten laden, door een XML-bestand bij PowerShell.exe te zetten met de naam PowerShell.exe.config en daarin het volgende op te nemen:
<configuration>
    <startup uselegacyv2runtimeactivationpolicy="true">
        <supportedruntime version="v4.0.30319">
        <supportedruntime version="v2.0.50727">
    </supportedruntime></supportedruntime></startup>
</configuration>

Of noem dit PowerShellISE.exe.config als het gaat om de ISE. Herstart PowerShell en je kunt "system.numerics.dll" toevoegen met Add-Type en alle BigIntegers gebruiken!


Geen opmerkingen:

Een reactie posten