Mit Milliarden rechnen

Übersicht BlitzBasic Beginners-Corner

Neue Antwort erstellen

 

Dirk Knoop

Betreff: Mit Milliarden rechnen

BeitragDo, Jun 24, 2010 19:25
Antworten mit Zitat
Benutzer-Profile anzeigen
Wie würdet ihr am einfachsten mit Blitz3D im Bereich von Milliarden rechnen ?

a=5*(1600000000): Print a
Hier kann Blitz3D schon nícht mehr, und es kommt ein negatives Ergebnis raus.

Ich möchte beispielsweise 500 Zahlen im Bereich von 10 bis 400.000.000 addieren, z.B.:

for a=1 to 500
zufall=rand(10,400000000)
alles=alles+zufall
next

print alles

Dirk Knoop
www.kostenloser-fussballmanager.de
www.discaim.de - weil Spaß kein Zufall ist
www.torchance.de - ein etwas anderer Fußball-Manager

Thunder

BeitragDo, Jun 24, 2010 19:30
Antworten mit Zitat
Benutzer-Profile anzeigen
Es gibt soweit ich weiß im Code-Archiv einige Stringrechner, die wie der Name schon sagt, Strings zum Rechnen verwenden und die Grundrechnungsarten (evtl. mehr) beherrschen.
Diese könnten aber zu langsam sein. Es ist aber afaik das einfachste.


mfg Thunder
Meine Sachen: https://bitbucket.org/chtisgit https://github.com/chtisgit

Midimaster

BeitragDo, Jun 24, 2010 22:10
Antworten mit Zitat
Benutzer-Profile anzeigen
wenn es wirklich nur ums Addieren oder Subtrahieren geht, könntest du ja ganze einfach bei Überschreitung der Millionengrenze immer die Millionen abziehen, und die in einer zweiten Variablen speichern:

BlitzBasic: [AUSKLAPPEN]
Global A_Unten%, B%, A_Oben%
a_unten=2000000123
b= 400000345
Print " A = " +A_unten
Print " B = " + b
Print " falsch = " + (a_unten +b)

A_Unten=Check(A_Unten)
B=Check(B)

A_Unten=A_Unten + B
A_Unten=Check(A_Unten)
Print "Ergebnis = " + A_Oben + Right("0000000" + A_Unten,6)


Function Check%(A%)
While a%>=1000000
A=A-1000000
A_Oben=A_Oben+1
Wend
Return A
End Function


Das ist vor allem superleicht zu verstehen

[EDIT]
Fehler im Code entfernt
  • Zuletzt bearbeitet von Midimaster am Fr, Jun 25, 2010 2:02, insgesamt einmal bearbeitet
 

n-Halbleiter

Betreff: Re: Mit Milliarden rechnen

BeitragDo, Jun 24, 2010 22:16
Antworten mit Zitat
Benutzer-Profile anzeigen
Dirk Knoop hat Folgendes geschrieben:
Hier kann Blitz3D schon nícht mehr, und es kommt ein negatives Ergebnis raus.


Die Größe der Beträge sorgt ja schon dafür, dass ein negativer Wert rauskommt, da hilft die Subtraktion von einer Million nicht mehr viel. :/

Die Idee ist aber nicht schlecht.

Theoretisch (nur mal so eine spontane Idee) könntest du auch Floats nutzen, bei denen der Wert 1 für 1Mio. steht. So sind z.B. 500.000 0,5. Das funktioniert nur nicht bei Werten wie 10, aber bei Werten ab 100.000 dürfte es nützlich werden, denke ich.

EDIT: @Midimaster: Dein Beispiel ist so übrigens nicht lauffähig...
mfg, Calvin
Maschine: Intel Core2 Duo E6750, 4GB DDR2-Ram, ATI Radeon HD4850, Win 7 x64 und Ubuntu 12.04 64-Bit
Ploing!
Blog

"Die Seele einer jeden Ordnung ist ein großer Papierkorb." - Kurt Tucholsky (09.01.1890 - 21.12.1935)

ToeB

BeitragDo, Jun 24, 2010 23:08
Antworten mit Zitat
Benutzer-Profile anzeigen
Das beste ist wirklich statt 1.000.000.000 mit 1000 zu rechnen (in Millionen), also wenn du hast

1.234.567.890 + 0.987.654.321

dann machst du daraus

1234,56789 + 987,654321 = 2222.222211

Also

2.222.222.211

Wink

Oder halt Stringrechner .. ISt eingl. Noch besser da dort so gut wie keine berechnungsfehler vorkommen und dazu nur viel größere Zahlen berechnet werden können. Nachteil : Langsam und fast nicht für echtezeit zu gebrauchen. Aber so große Zahlen denk ich mal brauchst du auch nicht für echtzeitanwendungen Wink

mfg ToeB
Religiöse Kriege sind Streitigkeiten erwachsener Männer darum, wer den besten imaginären Freund hat.
Race-Project - Das Rennspiel der etwas anderen Art
SimpleUDP3.0 - Neuste Version der Netzwerk-Bibliothek
Vielen Dank an dieser Stelle nochmal an Pummelie, welcher mir einen Teil seines VServers für das Betreiben meines Masterservers zur verfügung stellt!

Noobody

BeitragDo, Jun 24, 2010 23:24
Antworten mit Zitat
Benutzer-Profile anzeigen
n-halbleiter hat Folgendes geschrieben:
Theoretisch (nur mal so eine spontane Idee) könntest du auch Floats nutzen, bei denen der Wert 1 für 1Mio. steht. So sind z.B. 500.000 0,5. Das funktioniert nur nicht bei Werten wie 10, aber bei Werten ab 100.000 dürfte es nützlich werden, denke ich.

Die '1-für-1-Mio'-Definition ist so nicht ganz richtig. Floats werden im Mantisse-Exponent Format gespeichert, sprich, die Werte werden immer als x.xxxxxx*10^yy dargestellt. Wenn ich also 123'012.0 hinschreibe, wird im Float daraus 1.23012*10^5 daraus (wobei jeweils die 1.23012 und die 5 gespeichert werden). Das mit der '1-für-1-Mio' stimmt also nur, wenn man auch wirklich Zahlen in Millionengrösse angibt.

Floats sind allerdings für diese Aufgabe eher weniger geeignet, da sie nur 7 Stellen Genauigkeit haben. Man kann zwar Werte bis über Billiarden hinaus speichern, aber nur auf 7 Ziffern genau. Wenn also eine Rechnung 1'234'567'890'123'456'789 ergibt, wird nach der 7. Stelle abgeschnitten, also kommt 1'234'567'000'000'000'000 heraus. Für genaue Berechnungen sind Floats also eher ungünstig.

Du hast also entweder einen Stringrechner als Möglichkeit. Du könntest dir auch eine externe Lib schreiben, die mit long long ints rechnet (64-Bit, Wertelimit 2^63), oder du verwendest gar BCDs für unbegrenzte Genauigkeit (dafür brauchst du aber zusätzliche Libs).
Man is the best computer we can put aboard a spacecraft ... and the only one that can be mass produced with unskilled labor. -- Wernher von Braun

Midimaster

BeitragFr, Jun 25, 2010 3:14
Antworten mit Zitat
Benutzer-Profile anzeigen
@n-Halbleiter
Danke für den Hinweis, ich hab es gleich in Ordnung gebracht.

Die Zahlen, die er im Beispiel genannt hat, würden aber eine solche Vorgehensweise erlauben. Das Umkippen ins negative setzt ja erst nach 2.147.483.647. Wenn nur Zahlen unter 400.000.000 als Elemente hat und jedesmal das Ergebnis konvertiert, sollte es gut gehen.


So könnte es doch auch gehen, oder?

BlitzBasic: [AUSKLAPPEN]
Type Long
Field Oben%,Unten%, Sign%
End Type

Global AA.long = New long
Global BB.long = New long
Global CC.long = New long

SetLong AA,2100000123

SetLong BB,400000345

PrintLong AA
PrintLong BB

; Verwendung: wie CC= AA + BB
AddLong CC, AA, BB

PrintLong CC


Function SetLong(A.Long, Wert%)
; füllt LONG-Zahl mit einem INTEGER-Wert
a\Sign=Sgn(Wert)
wert=Abs(Wert)
A\Oben=Int(Wert/1000000000)
A\Unten=Wert Mod 1000000000
End Function



Function PrintLong(A.Long)
;setzt Werte zu einem String zusammen
Local vz$
If a\Sign=-1 Then
vz="-"
Else
vz="+"
EndIf
If a\Oben>0 Then
Print vz + A\Oben + Right("000000000"+A\Unten,9)
Else
Print vz + a\Unten
EndIf
End Function



Function AddLong(C.long, A.long, B.long)
; C=A*B
; funktioniert auch mit negativen LONGs
; auch erlaubt: A=A+A

Local locA.Long= New long
locA\unten=A\Unten
locA\oben=A\Oben
locA\sign=A\Sign

Local locB.Long= New long
locB\unten=B\Unten
locB\oben=B\Oben
locB\sign=B\Sign

C\Sign=A\sign

If locA\sign <> locB\sign Then
C\unten=locA\Unten-locB\Unten
If C\Unten<0 Then
C\Oben=C\oben-1
C\Unten=C\Unten+1000000000
EndIf
C\oben=C\oben-locB\oben
If C\oben<0 Then
C\sign=-C\sign
EndIf
Else
C\unten=locA\Unten + locB\Unten
If C\Unten>=1000000000 Then
C\Oben = C\oben+1
C\Unten = C\Unten-1000000000
EndIf
C\oben=C\oben+locB\oben
EndIf
End Function



Function SubLong(C.long, A.long, B.long)
; C=A-B
; Subtraktionsfunktion

Local locB.Long= New long
locB\unten=B\Unten
locB\oben=B\Oben
locB\sign=-B\Sign

AddLong A, locB, C
End Function

TimBo

BeitragFr, Jun 25, 2010 11:51
Antworten mit Zitat
Benutzer-Profile anzeigen
man kann aber große Zahlen mit Integern und Floats darstellen.

Zahl = Integer*Offset + Float.

leider weiß ich nicht wie groß eine Float werden kann, deshalb vergebt mir, dass ich Offset hingeschrieben habe.

Grüße
TimBo
mfg Tim Borowski // CPU: Ryzen 2700x GPU: Nvidia RTX 2070 OC (Gigabyte) Ram: 16GB DDR4 @ 3000MHz OS: Windows 10
Stolzer Gewinner des BCC 25 & BCC 31
hat einen ersten Preis in der 1. Runde beim BWInf 2010/2011 & 2011/12 mit BlitzBasic erreicht.

Midimaster

BeitragFr, Jun 25, 2010 13:43
Antworten mit Zitat
Benutzer-Profile anzeigen
das Problem der FLOAT-Variablen besteht aber darin, dass sie eben nicht auf die Basis 10^n, sondern auf 2^n basieren. Dies bedeutet grobe Rundungsfehler bereits bei Zahlen ab mehr als 9 Stellen:

BlitzBasic: [AUSKLAPPEN]
A#=1234567.0 * 100.0
Print a

Noobody

BeitragFr, Jun 25, 2010 14:45
Antworten mit Zitat
Benutzer-Profile anzeigen
Midimaster hat Folgendes geschrieben:
das Problem der FLOAT-Variablen besteht aber darin, dass sie eben nicht auf die Basis 10^n, sondern auf 2^n basieren.

Die Rundungsfehler haben aber nichts damit zu tun, sondern mit der Mantisse, die nur 23 Bits zur Verfügung hat. Da ist es klar, dass nur eine begrenzte Genauigkeit zur Verfügung steht.

Dass Floats die Basis 2 verwenden, bringt aber ein anderes Problem - gewisse Dezimalzahlen können in Binär nicht dargestellt werden (z.B. 0.1 oder 0.4). Zwar werden diese Zahlen angenähert, aber für exakte Anwendungen ist das auch nicht genau genug.
Man is the best computer we can put aboard a spacecraft ... and the only one that can be mass produced with unskilled labor. -- Wernher von Braun

Midimaster

BeitragFr, Jun 25, 2010 15:56
Antworten mit Zitat
Benutzer-Profile anzeigen
@Noobody

(Anmerkung: die folgenden Punkte sind Tausender-Stellen)
dann rechne mal nach 1.234.567 passt eigentlich in 23 bit! Da gehen Zahlen rein bis 8.388.608

1.234.567 * 100 ist eigentlich 1.234.567 *10^2 es kommt aber 123.457 *10^3 raus. Da ist die Mantisse gar nicht ausgenutzt


Unter BMax kommt dann folgendes raus:

1.234.567 * 100 ist 123.456.704

Noobody

BeitragFr, Jun 25, 2010 16:26
Antworten mit Zitat
Benutzer-Profile anzeigen
@Midimaster: In B3D kommt genau dasselbe wie in BMax heraus - nämlich 123.456.704. Warum steht dann aber 123.457.000 in B3D? Das liegt daran, dass Print in B3D auf die 6. Stelle rundet, bevor eine Kommazahl ausgegeben wird.

Wenn du aber die Binärrepresentationen vom B3D-Ergebnis und vom BMax-Ergebnis vergleichst, wirst du feststellen, dass dasselbe Resultat herauskommt. BlitzBasic: [AUSKLAPPEN]
Local Bank = CreateBank( 4 )

PokeFloat Bank, 0, 1234567.0 * 100.0

Print Bin( PeekInt( Bank, 0 ) )
WaitKey
End

BlitzMax: [AUSKLAPPEN]
Local A:Float = 1234567.0:Float*100.0:Float

Print Bin( Int Ptr( Float Ptr( Varptr A ) )[ 0 ] )
Man is the best computer we can put aboard a spacecraft ... and the only one that can be mass produced with unskilled labor. -- Wernher von Braun
 

Dirk Knoop

BeitragSa, Jun 26, 2010 15:09
Antworten mit Zitat
Benutzer-Profile anzeigen
Vielen Dank für eure Anregungen und Ideen.
Ich habe das Problem nun so gelöst, dass ich zusätzlich einen Zähler für 100.000.000 eingebaut habe.

Dirk Knoop
www.kostenloser-fussballmanager.de
www.discaim.de - weil Spaß kein Zufall ist
www.torchance.de - ein etwas anderer Fußball-Manager

Neue Antwort erstellen


Übersicht BlitzBasic Beginners-Corner

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group