AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Projekte Rechenprogramm
Thema durchsuchen
Ansicht
Themen-Optionen

Rechenprogramm

Ein Thema von Amateurprofi · begonnen am 31. Mai 2009 · letzter Beitrag vom 15. Jun 2025
Antwort Antwort
Amateurprofi

Registriert seit: 17. Nov 2005
Ort: Hamburg
1.111 Beiträge
 
Delphi XE2 Professional
 
#1

AW: Rechenprogramm

  Alt 26. Sep 2020, 23:44
Hallo Profi
Wichtigere Frage... Wieso kann ich mit deinem Rechner "nur" bis 1754! rechnen?
Gruss
M
Hab ich mit PN beantwortet, hier noch mal für andere.

Das Maximum 1754 für N! (im Normal-Modus) resultiert aus dem größten in einem Extended darstellbaren Wert (1.1E+4932).
1755! ergäbe 3.473E+4933 und würde den Maximalwert überschreiten.

Übrigens:
Im Normal-Modus werden in meinem Programm alle Werte in Extended-Variablen gespeichert, was auch der Grund ist, warum es keine 64Bit Version gibt (Da ist Extended = Double).

Tatsächlich rechne ich N! mit der FPU. Hier der Code
Delphi-Quellcode:
PROCEDURE MonOpFacul(var V:TValue);
asm // EAX=@TValue
// CheckMinMax(v.v,0,1754,pact,116);
// n:=Trunc(v.v);
// v.v:=1;
// while n>1 do begin
// v.v:=v.v*n;
// dec(n);
// end;
          // ASM Version braucht 1/6 der Zeit und ist kürzer, auch wenns
          // nicht so aussieht.
                   mov byte [eax].TValue.Vt,vtNone
                   fld tbyte[eax].TValue.V
                   fldz
                   fcomip st,st(1)
                   ja @Err
                   fild dword [@1754]
                   fcomip st,st(1)
                   jae @Ok
 @Err: mov eax,117
                   mov edx,pact
                   jmp ASMError1
 @1754: dd 1754
 @Ok: sub esp,8
                   fnstcw word [esp+4]
                   fnstcw word [esp+6]
                   fwait
                   or word [ESP+4], $0F00 // trunc toward zero, full precision
                   fldcw word [ESP+4]
                   fistp dword [esp]
                   fwait
                   fldcw word [esp+6]
                   fld1
                   mov edx,[esp]
                   sub edx,1
                   jbe @Fin
 @Loop: fimul dword [esp]
                   mov [esp],edx
                   sub edx,1
                   ja @Loop
 @Fin: fstp tbyte[eax].TValue.V
                   add esp,8
end;
Delphi-Quellcode:
   // Vom Parser benutzter Werte-Record
    // CanDeformat : Info, ob der von NumStr erzeugte Ausgabe-String
    // wieder deformatiert werden kann
    // Vt : Wofür der Wert steht
    // V : Der numerische Wert
    // Numerator : Zähler, wenn Vt=vtFraction
    // Denominator : Nenner, wenn Vt=vtFraction
    // Latitude : Breitengrad, wenn Vt=vtGeoPos
    // Longitude : Längengrad, wenn Vt=vtGeoPos
    // ClrVal : Fabbdaten, wenn Vt=vtColor
    TValue=packed Record
       CanDeformat:Boolean;
       Vt:TValueType;
       V:Extended;
       case Integer of
          1 : (Numerator:Extended;
                 Denominator:Extended);
          2 : (Latitude:Extended;
                 Longitude:Extended);
          3 : (LatLon:Array[Boolean] of Extended);
          4 : (ClrVal:TColorValue);
    end;
  // Wofür ein Wert steht (vtNone=einfache Zahl)
    TValueType=(vtNone,vtBool,vtColor,vtFraction,
                vtSeconds,vtMinutes,vtHours,vtDays,vtWeeks,vtMonths,vtYears,
                vtTime,vtDate,vtDateTime,
                vtGeoPos);
Gruß, Klaus
Die Titanic wurde von Profis gebaut,
die Arche Noah von einem Amateur.
... Und dieser Beitrag vom Amateurprofi....
  Mit Zitat antworten Zitat
Michael II

Registriert seit: 1. Dez 2012
Ort: CH BE Eriswil
772 Beiträge
 
Delphi 11 Alexandria
 
#2

AW: Rechenprogramm

  Alt 27. Sep 2020, 06:25
Besten Dank!

Du könntest
x = e^ln(x) bzw. hier besser
x = 10^lg(x) und
log(ab)=log(a)+log(b)
ausnutzen.

Dann kannst du x! schreiben als x! = 10^lg(1*2*3...*x) = 10^(lg(1)+...lg(x)).

Fürs Coden: Du berechnest zuerst
s = lg(1)+...lg(x)

Sei s = e + m, wobei e = trunc(s) und m = frac(s)

x! = 10^s = 10^(e+m) = 10^m * 10^e.

Output:
10^m rechnest du aus, e lässt du als Exponent stehen.

Ich fühl mich gerade zurückversetzt in die Zeiten des hp41CV... .
Michael Gasser

Geändert von Michael II (27. Sep 2020 um 06:31 Uhr)
  Mit Zitat antworten Zitat
Amateurprofi

Registriert seit: 17. Nov 2005
Ort: Hamburg
1.111 Beiträge
 
Delphi XE2 Professional
 
#3

AW: Rechenprogramm

  Alt 27. Sep 2020, 10:01
Besten Dank!

Du könntest
x = e^ln(x) bzw. hier besser
x = 10^lg(x) und
log(ab)=log(a)+log(b)
ausnutzen.

Dann kannst du x! schreiben als x! = 10^lg(1*2*3...*x) = 10^(lg(1)+...lg(x)).

Fürs Coden: Du berechnest zuerst
s = lg(1)+...lg(x)

Sei s = e + m, wobei e = trunc(s) und m = frac(s)

x! = 10^s = 10^(e+m) = 10^m * 10^e.

Output:
10^m rechnest du aus, e lässt du als Exponent stehen.

Ich fühl mich gerade zurückversetzt in die Zeiten des hp41CV... .
Das wäre aber eine schöne Verschlimmbesserung.
Statt (für N=1000) hätte ich statt 1000 Multiplikationen 1000 mal Log10(), und Log10() braucht seine Zeit.
Gruß, Klaus
Die Titanic wurde von Profis gebaut,
die Arche Noah von einem Amateur.
... Und dieser Beitrag vom Amateurprofi....
  Mit Zitat antworten Zitat
Michael II

Registriert seit: 1. Dez 2012
Ort: CH BE Eriswil
772 Beiträge
 
Delphi 11 Alexandria
 
#4

AW: Rechenprogramm

  Alt 27. Sep 2020, 10:58
Du hast natürlich Recht. Das von mir vorgeschlagene "Verfahren" ist mathematischer Bocks-Mist. Es führt zwar aufs richtige Resultat. Aber der Weg.... [Ich war soeben beim Ponys Misten und obschon es auf 800müM bereits ziemlich kalt und windig ist, war die Jacke plötzlich völlig überflüssig als mir einfiel, dass das was ich geschrieben.... Du kannst natürlich direkt Mantisse und Exponent separieren und über die 1754! Grenze hinaus multiplizieren... ich lasse es zur Belustigung stehen... ]


Ich schlage dieses Verfahren ja nicht für "kleine" Werte von x (also nicht für x <= 1754) vor. Mir ist vollkommen klar, dass der Aufwand via log10 weit grösser ist. Wenn ich dich aber richtig verstehe, kann dein Programm Näherungswerte "nur" bis 1754! berechnen, dann ist aus.

Wenn du aber über den Exponenten zur Basis 10 rechnest, kommst du an Orte, wo nie jemand zuvor gewesen ist.

Du könntest deine Superschnellmethode bis 1754 nutzen und ab dann via log die Näherungswerte berechnen.

Für grosse Werte - kommen in der Statistik durchaus vor - könnte dein Programm zum Beispiel jeden 100sten ! Wert tabellieren; dann müsstest du nicht allzu viele log10 addieren.

War nur ein Vorschlag - mehr nicht.

Besten Dank für deine Tipps zu "tief" und Co (Kombinatorik Teil in deinem Calculator).
Michael Gasser

Geändert von Michael II (27. Sep 2020 um 15:05 Uhr)
  Mit Zitat antworten Zitat
Amateurprofi

Registriert seit: 17. Nov 2005
Ort: Hamburg
1.111 Beiträge
 
Delphi XE2 Professional
 
#5

AW: Rechenprogramm

  Alt 27. Sep 2020, 17:10
Ich schlage dieses Verfahren ja nicht für "kleine" Werte von x (also nicht für x <= 1754) vor. Mir ist vollkommen klar, dass der Aufwand via log10 weit grösser ist. Wenn ich dich aber richtig verstehe, kann dein Programm Näherungswerte "nur" bis 1754! berechnen, dann ist aus.
In dem Programm werden im "Normal"-Modus zur Speicherung der Daten Extended-Variablen verwendet, und da gibt es nun einmal die Obergrenze 1.1E+4932

Anders ist es im "BigDecimal"-Modus.
Da kannst du die Fakultät bis 10000 berechnen. Exact übrigens und nicht nur näherungsweise.
Die 10000 als Obergrenze für Fakultät ist willkürlich festgelegt.

Allerdings können diese im Ausgabefeld nicht in voller Länge angezeigt werden.
Das hatte ich hier https://www.delphipraxis.net/195060-...extlaenge.html einmal angesprochen.

Aber mache einmal folgendes:
Stelle auf "BigDecimal"-Modus (2tes Panel in der Statusbar)
Stelle "Auch Integerzahlen in technischer Darstellung" auf "Nein" (9tes Panel in der Statusbar)
Gib 10000! ein.
Als Rechenergebnis erhältst du "Zahl zu lang" in grüner Schrift.
Rechtsklicke den Text.
In einem PopUp-Menu wird angeboten, die Zahl ins Clipboard zu stellen oder in einer Datei zu speichern.
Wenn du in Datei speichern wählst, wird in der Datei "Log.txt" im Programmverzeichnis gespeichert.
Oder rechtsklicke den Text mit gedrückter Ctrl-Taste.
Dann wird der "Dialog für lange Zahlen" geöffnet, in dem du die Zahl (in Worten) ansehen kannst.
Im Anhang findest du 2 Dateien, die Zahl in Ziffern, die Zahl in Worten.
Angehängte Dateien
Dateityp: zip 10000!.zip (86,3 KB, 7x aufgerufen)
Gruß, Klaus
Die Titanic wurde von Profis gebaut,
die Arche Noah von einem Amateur.
... Und dieser Beitrag vom Amateurprofi....
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 11:49 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz