Fakultät berechnen, programm per CMD?

emily611  25.02.2021, 13:55

Das geht einfacher mit Linux

simoncaspar 
Fragesteller
 25.02.2021, 13:57

Sollte unter Windows sein. Wie ist eigentlich egal.

Oubyi, UserMod Light  25.02.2021, 14:01

Im Prinzip sollte das ein simpler Code sein, aber 6000! ist extrem "heftig".


Was willst Du damit? Ich denke jenseits von 70! (=1.197857e+100) wird es langsam uninteressant?!

simoncaspar 
Fragesteller
 25.02.2021, 14:02

Interessiert mich einfach. Dass die Zahl riesig ist, weiß ich selbst.

7 Antworten

Vom Fragesteller als hilfreich ausgezeichnet

Pures Batch ist hinsichtlich rechnen auf Integer beschränkt:

demo.cmd

@echo off
chcp 65001 >nul

set /p "fac=von welcher Zahl soll ich die Fakultät berechnen?"
if %fac% gtr 12 (
  echo Batch kann nur bis 2147483647 rechnen
  echo das Ergebnis von wäre größer.
  pause
  exit /b
)

set "__result=1"
for /l %%a in (1,1,%fac%) do (
  set /a "__result*=%%a"
)
echo %fac%!= %__result%
pause

...damit wäre mit purem Batch bei 12! schluss.

Mit Powershell ab v3.0 , .Net, Java ,usw. kann man den Datentyp Bigint nutzen.

(Mit den klassischen größten numerischen StandardDatentyp [double] dürfte bei einer Fakultät von 270 schluss sein.

1..170 |%{$res=1}{$res*=$_}{$res}
1..171 |%{$res=1}{$res*=$_}{$res}

)

Aber Vorsicht Bigint kennt keine Unter-/Obergrenzen , wenn es Hart auf Hart kommt werden Biginteger berechnet bis die Zahl den gesamten für die Anwendung verfügbaren Speicher füllt!

Hier aber kein Problem eher schläfst Du vor dem Rechner ein.... (100000! rechnet ca 10 Sekunden)

demo.ps1

[uint64]$fac=Read-Host -Prompt 'von welcher Zahl soll ich die Fakultät berechnen?'
  #berechne Fakultät
$Ergebnis=1..$fac |%{[bigint]$res=1}{$res*=$_}{$res}
'{0}! = {1}' -f $fac,$Ergebnis
pause

Es geht natürlich auch einfach nur die Berechnung durch Powershell innerhalb einer Batch auszuführen

@echo off
set /p "fac=von welcher Zahl soll ich die Fakultaet berechnen?"
powershell "1..%fac%|%%{[bigint]$res=1}{$res*=$_}{$res}"
pause

...aber in Batch kannst du kein Ergebnis >ca.8000 Stellen einer Variable zuweisen!

Demo.cmd

@echo off
set /p "fac=von welcher Zahl soll ich die Fakultaet berechnen?"
  rem ab ca 2700 (ausgabe der Komandozeile >8190 Zeichen) vesagt eine Batchschleife!
for /f %%a in ('powershell "1..%fac%|%%{[bigint]$res=1}{$res*=$_}{$res}"') do (set "__result=%%a")
echo %fac%!= %__result%
pause
Woher ich das weiß:eigene Erfahrung – Ich mach das seit 30 Jahren
simoncaspar 
Fragesteller
 26.02.2021, 12:27

Danke, das hat mir sehr geholfen. Ich habe das Powershell-Script verwendet. Hättest du zufällig noch eins parat um die Zahl durch 2 zu teilen?

0
Erzesel  26.02.2021, 17:43
@simoncaspar

Einfach Rechnen:

$var=244
$Ergebnis=$var/2
'{0} / 2 = {1}' -f $var,$Ergebnis
[uint64]$fac=Read-Host -Prompt 'von welcher Zahl soll ich die Fakultät berechnen?'
 #berechne Fakultät
$Ergebnis=1..$fac |%{[bigint]$res=1}{$res*=$_}{$res}
$Ergebnis/=2
'{0}!/2 = {1}' -f $fac,$Ergebnis
pause

...da Biginteger immer ganze Zahlen sind , ergibt das Teilen durch 2 für die einzige ungerade Fakultät (1) den wert 0

Mit solchen Riesenzahlen zu operieren ist nicht sehr üblich.

Für kleinere Bigints genügt ein Typecast:

[bigint]$langeZahl=11111
$langeZahl/3 ;
  #typecast
([double]$langeZahl)/3 ;

Für bei großen Zahlen sind Nachkommastellen mit etwas Rödelei verbunden... (mit dem Ergebnis lässt sich nicht mehr Rechnen ---ist einfach ein String---)

  #bigint-Constante  als String  übergeben (wird implizit gewandelt)
[bigint]$Divident='1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111'
$Divisor=3
[double]$Rest=0
  #teilen mit Rest (der rest  wird in eien Referenzierte Variable gespeichert)
$Quotient=[system.numerics.BigInteger]::DivRem($Divident,$Divisor,[ref]$Rest)
'Quotient={0}' -f $Quotient
'Rest    ={0}' -f $Rest
  #für Nachkommastellen Rest/Divisor teilen (Ergebnis immer <1) und  diese per regex abspalten
$fraction=[regex]::match($Rest/$Divisor,'(?<=\.)(\d+)').value
'Nachkomastellen={0}' -f $fraction
  #das Übrige ist Stringrödelei  GanzzahligerQuotiet+landestypischesDezimalzeichen+Nachkommastellen
$ultralangeFloatZahl='{0}{1}{2}' -f $Quotient,((get-culture).NumberFormat.NumberDecimalSeparator),$fraction
$ultralangeFloatZahl
pause

Letzteres ist lediglich ein Gedankenspiel für die Ausgabe einer sehr großen Zahl mit Kommastellen .

Viel Spaß beim Basteln

0
verreisterNutzer  24.03.2021, 09:27

Hab nicht ganz verstanden bis zu welcher Fakultät welcher deiner Rechner rechnen kann, könntest du das noch einmal erläutern? (Also welche maximale Zahl man am Anfang eingeben kann für die dann kein Ergebnis mehr berechnet werden kann)

0
Erzesel  24.03.2021, 18:18
@verreisterNutzer

Eigentlich musst Du lediglich die Scripte ausführen um zu sehen was passiert...😏

Batch sind die Dinger mit dem echo off am Anfang und werden einfach als Datei mit der Endung .cmd gespeichert... (egal ob innerhalb ein Powershell inliner aufgerufen wird...

Das Zeug ohne echo off , mit den vielen $-Zeichen ist PoweshellScript. und kann theoretish direkt in der PS-Console oder ISE ausgeführt werden... einfach reinkopieren... oder als PS1.Datei speichern...

....egal, soviel zu den Basics.🥱

Die erste Batch habe ich auf 12 begrenzt da sdas Ergebnis von13! = 6227020800 nicht mehr in einen 32bit-Integer passt. Und in Batch ziemlich willkürlich alle Bits über abgehakt werden... das wars schon...

Die Powershells , welche ohne Bigint Rechnen arbeiten mit dem Datentyp double dieser kann Zahlen bis 1.7976931348623157E+308 aufnehmen (aber nur gerundet... bei einer Fakultät von 170 ist Schluss.

alle 171 anzeigen...

1..171 |%{$res=1}{$res*=$_;$res}

Die PS-Scripte mit Bigint können ganze Zahlen theoretisch die Größe deines Speichers haben... die Darstellbarkeit ist jedoch auf eine Länge von 2147483647 Dezimalziffern begrenzt. (maximale Stringlänge für die Ausgabe)

Welche Fakultät da reinpasst? keine Ahnung. Ich habe bei 1 Mio aufgehört, weil dann die Rechenzeit exponentiell ansteigt. (man kann mit dieser einfachen Formel auch nicht mit mehreren Kernen rechnen, da jeder Wert vom vorangegangenen abhängt,

Während die Fakultät vom 200000 eine Rechenzeit von unter einer Minute hat sind es bei 500000 schon 7 Minuten (auf einer 4,3GHz-Maschine). Bei 1000000! liege ich bereits im Bereich von Stunden. Für 500Mio! dürfte man schon einige Monate rechnen. Ergo kann man nur recht schwer abschätzen, wann 2,14Mrd Stellen überschritten werden.

Dieser lineare Algorithmus für die Berechnung ist in diesem Fall aber auch extrem simpel... Es gibt schnellere, aber ich bin kein Mathematiker...

1

Hole dir eine freie IDE wie codeblocks für Windows und programmiere das mit c++.

Man braucht aber ganz schön Erfahrung für so was. Libqadmath sollte auc hinstalliert sein. Weis aber nicht, ob letztere für Windows auf verfügbar ist.

Woher ich das weiß:eigene Erfahrung

Das geht mit den herkömmlichen integer-Datentypen nicht. Selbst nicht mit einer

unsigned int-Variable mit 128 Bit. Bei long double (sollte eigentlich ein Integer-Typ sein, aber kein anderer Datentyp packt mehr) bis zu 1550 Fakorielle. Bei Quadmath mit Linux habe ich mal bis 16384 Faktorielle gearbeitet(auf Linux). Ich habe mal ein Verschlüsselungsprogramm geschrieben das mit Transposition auf Bitebene arbeitet.

Der Hacken dabei ist die Zahlen werden zu Basis 2 dargestellt, nicht im Dezimalsystem.

Woher ich das weiß:eigene Erfahrung

In Python haben int-Werte beliebige Genauigkeit:

from math import factorial
print( factorial(6000) )

Die Berechnung dauert etwa 1 ms, aber versuche besser nicht, das Ergebnis in einer DOS-Box anzuzeigen. Die Zeichenausgabe ist in cmd.exe unerträglich langsam. Schreibe die Zahl lieber in eine Datei und schau sie Dir im Editor an.

Bis 6000! ? Das ist nicht mehr ganz trivial. 3000! hat schon über 9000 Stellen.

Ich denke, da wirst du dir erst einmal etwas zur Datenhaltung selber überlegen müssen.

simoncaspar 
Fragesteller
 25.02.2021, 14:01

ja. Das ist mein Problem.

0
CSANecromancer  25.02.2021, 14:05
@simoncaspar

Was evtl. ginge (aber das dauert dann schätzungsweise EXTREMST in der Berechnung), dass du die einzelnen Stellen/Ziffern der Zahl tatsächlich in einem Array anlegst. Die Berechnung der einzelnen(!) Fakultäten müsstest du dann über das Array iterieren lassen und auch das Stellenwertshiften selbst übernehmen (von rechts nach links).

Am Ende könntest du dann den Arrayinhalt sequentiell ausspucken und hättest so deine Zahl. Aber ich will nicht einmal abschätzen, wie lange die Transformation der arithmetischen Operationen auf ein Array dauern würden.

0