Rechnen mit großen Zahlen

Übersicht BlitzMax, BlitzMax NG Codearchiv & Module

Neue Antwort erstellen

BlitzMoritz

Betreff: Rechnen mit großen Zahlen

BeitragFr, März 12, 2010 23:07
Antworten mit Zitat
Benutzer-Profile anzeigen
Zufällig bin ich auf die Seite "projecteuler" gestoßen und habe mich mit großer Begeisterung auf die dort zu knobelnden Algorithmen-Aufgaben gestürzt. Selbstverständlich war es eine Frage der Ehre, BlitzMax zu verwenden Wink .
Rasch und immer wieder stieß ich jedoch auf Probleme mit sehr großen Zahlen wie etwa 2^1000, für die BlitzMax (bekanntermaßen Rolling Eyes ) keine Datentypen bereitstellt. Kurzerhand habe ich mir dann die grundlegenden Funktionen selbst geschrieben. Wie im Titel beschrieben, geht es um die Menge der ganzen Zahlen, die man mit meinen Funktionen addieren, subtrahieren, multiplizieren, dividieren, Wurzelziehen, vergleichen, potenzieren und die Fakultät errechnen kann. Der Weg läuft - selbstverständlich - über String-Zeichenketten. Superstrict ist erforderlich.
Zum schnellen Ausprobieren sei hier erst einmal ein kleiner Demo-Code eingefügt:
BlitzMax: [AUSKLAPPEN]
SuperStrict
Include "Calculate_StringInts.bmx"
Local a:String = "230498170394817039847220938470950002347873438404"
Local b:String = "-120928700037409384700128372877293204793749823394870233"
Local c:String
Print
Print "----------------------------------------------------------"
Print "Demonstration BM's StringInt-Functions fuer Ganze Zahlen"
Print "----------------------------------------------------------"
Print
Print "Beispielzahl a = " + a
Print "Beispielzahl b = " + b
Print
Print "Addition:"
c = Add_StringInts(a, b)
Print "c := a + b = " + c
Print
Print "Subtraktion:"
Print "c - b = a = " + Subtract_StringInts(c, b)
Print
Print "Multiplikation:"
c = Multiply_StringInts(a, b)
Print "c := a * b = " + c
Print
Print "Division:"
Print "c / b = a = " + Divide_StringInts(c, b)
Print
Print "Vergleich (0 = gleich, 1 = 1.Wert groesser, 2 = 2.Wert groesser):"
Print "Compare_StringInts(a, b) = " + Compare_StringInts(a, b)
Print
Print "Potenzen:"
Print "2 hoch 1000 = " + Power_Ints(2,1000)
Print
Print "Quadratwurzeln (falls noetig, abgerundet auf ganze Zahlen):"
Print "Wurzel aus a = " + Sqr_StringInt(a)
Print
Print "Fakultaet:"
Print "200! = " + Fac_Int(200)
Print
Print "----------------------------------------------------------"
Print "Und beliebige Kombinationen und Tests:"
Print "----------------------------------------------------------"
Print
Print "Die Wurzel aus 17 hoch 258:"
Print Sqr_StringInt(Power_Ints(17, 258))
Print "sollte dasselbe sein wie 17 hoch 129"
Print Power_Ints(17,129)
Print
Print "Die Wurzel aus 3 hoch 648:"
Print Sqr_StringInt(Power_Ints(3, 648))
Print "sollte dasselbe sein wie 81 hoch 81"
Print Power_Ints(81,81)
Print
Print "Die Wurzel aus 28561 hoch 74:"
Print Sqr_StringInt(Power_Ints(28561, 74))
Print "sollte dasselbe sein wie 13 hoch 148"
Print Power_Ints(13, 148)
Print
Print "----------------------------------------------------------"
Print "Viel Spass beim 'Spielen'..."
Print "----------------------------------------------------------"

Und hier kommt dann die ziemlich große "Calculate_StringInts.bmx"-Datei, die alle Funktionen bereitstellt:

BlitzMax: [AUSKLAPPEN]
'######################################
Function Compare_StringInts:Int(StringInt1:String, StringInt2:String)
'######################################
Local sign1:String = Left(StringInt1,1)
Local sign2:String = Left(StringInt2,1)
If sign1 <> "-" Then
If sign2 = "-" Then Return 1
Else '(sign1 = "-")
If sign2 <> "-" Then
Return 2
Else '(sign2 = "-")
StringInt1 = Right(StringInt1, Len(StringInt1)-1)
StringInt2 = Right(StringInt2, Len(StringInt2)-1)
End If
End If
Local Len1:Int = Len(StringInt1)
Local Len2:Int = Len(StringInt2)
If Len1 = Len2 Then
Local single_digit:Int = 1
While single_digit =< Len1
If Int(Mid(StringInt1, single_digit, 1)) <> Int(Mid(StringInt2, single_digit, 1)) Then
If Int(Mid(StringInt1, single_digit, 1)) > Int(Mid(StringInt2, single_digit, 1)) Then
If sign1 <> "-" Then Return 1
Return 2
Else
If sign1 <> "-" Then Return 2
Return 1
End If
End If
single_digit = single_digit + 1
Wend
Return 0
ElseIf Len1 > Len2 Then
If sign1 <> "-" Then Return 1
Return 2
Else '(If Len1 < Len2)
If sign1 <> "-" Then Return 2
Return 1
End If
'######################################
End Function '(compare_StringInts)
'######################################

'######################################
Function Power_Ints:String(integer1:Int, integer2:Int)
'######################################
If integer2 > 1 Then
Local sign:String
If integer1 < 0 Then
integer1 = -integer1
If integer2 / 2 * 2 <> integer2 Then sign = "-"
End If
'--------------------------------------------------------------------
Local TempStringInt:String = power_Ints(integer1, integer2/2)
If integer2 / 2 * 2 = integer2 Then Return sign + multiply_StringInts(TempStringInt, TempStringInt)
TempStringInt = multiply_StringInts(TempStringInt, TempStringInt)
Return sign + multiply_StringInts(TempStringInt, integer1)
ElseIf integer2 = 1 Then
Return String(integer1)
ElseIf integer2 = 0 Then
Return "1"
Else '(integer2 < 0)
Return "0"
End If
'######################################
End Function '(power_Int)
'######################################

'######################################
Function Sqr_StringInt:String(StringInt:String)
'######################################
Local LeftDigit:String = Left(StringInt, 1)
If LeftDigit = "-" Then Return "ERROR"
Local count_digits:Int = Len(StringInt)
If count_digits < 18 Then Return String(Long(Sqr(Long(StringInt))))
Local x0:String, y0:String, x:String, y:String, Memo_x:String
If count_digits / 2 * 2 = count_digits Then
Local Top:String = "1000000000"
Local Length:String = "68377224"
Local d:Int = 9
While d < count_digits/2
Top = Top + "0"
Length = Length + "0"
d = d + 1
Wend
x = subtract_StringInts(Top, multiply_StringInts(Length, LeftDigit))
Else
Local Down:String = "1000000000"
Local Length:String = "216227766"
Local d:Int = 9
While d < count_digits/2
Down = Down + "0"
Length = Length + "0"
d = d + 1
Wend
x = add_StringInts(Down, multiply_StringInts(Length, LeftDigit))
End If
y = multiply_StringInts(x, x)
Repeat 'Newton:
x = subtract_StringInts(x, divide_StringInts(subtract_StringInts(y, StringInt), add_StringInts(x, x)))
y = multiply_StringInts(x, x)
x0 = subtract_StringInts(x, "1")
y0 = multiply_StringInts(x0, x0)
If y = StringInt Or Memo_x = x Then
Return x
ElseIf compare_StringInts(y, StringInt) = 1 And compare_StringInts(y0, StringInt) <> 1 Then
Return x0
End If
Memo_x = x
Forever
'######################################
End Function '(Sqr_StringInt)
'######################################

'######################################
Function Fac_Int:String(integer:Int)
'######################################
If integer > 12 Then
Local StringInt:String = "479001600"
For Local i:Int = 13 To integer
StringInt = multiply_StringInts(StringInt, i)
Next
Return StringInt
ElseIf integer > 0 Then
Local simple_fac:Int = 1
For Local i:Int = 2 To integer
simple_fac = simple_fac * i
Next
Return String(simple_fac)
Else
Return "0"
End If
'######################################
End Function '(fac_Int)
'######################################

'######################################
Function Multiply_StringInts:String(StringInt1:String, StringInt2:String)
'######################################
Local StringInt3:String, TempLong:Long[2], digits9_1:Int, digits9_2:Int, zero9:Int
Local TempString:String, sign:String = ""
If Left(StringInt1, 1) <> "-" Then
If Left(StringInt2, 1) = "-" Then
sign = "-"
StringInt2 = Right(StringInt2, Len(StringInt2)-1)
End If
Else '(Left(StringInt1, 1) = "-")
StringInt1 = Right(StringInt1, Len(StringInt1)-1)
If Left(StringInt2, 1) <> "-" Then
sign = "-"
Else '(Left(StringInt2, 1) = "-")
StringInt2 = Right(StringInt2, Len(StringInt2)-1)
End If
End If
Local Len1:Int = Len(StringInt1)
Local Len2:Int = Len(StringInt2)
Repeat
digits9_1 = digits9_1 + 9
TempLong[0] = Long(Mid(StringInt1, Len1 + 1 - digits9_1, 9))
digits9_2 = 9
Repeat
'----------------------------------------------
TempLong[1] = Long(Mid(StringInt2, Len2 + 1 - digits9_2, 9))
TempString = String(TempLong[0] * TempLong[1])
zero9 = (digits9_1 - 9) / 9 + (digits9_2 - 9) / 9
For Local z:Int = 1 To zero9
TempString = TempString + "000000000"
Next
StringInt3 = add_StringInts(StringInt3, TempString)
'----------------------------------------------
If digits9_2 >= Len2 Then Exit
digits9_2 = digits9_2 + 9
Forever
If digits9_1 >= Len1 Then Exit
Forever
Return sign + StringInt3
'######################################
End Function '(multiply_StringInts)
'######################################

'######################################
Function Divide_StringInts:String(StringInt1:String, StringInt2:String)
'######################################
If StringInt2 = 0 Then Return "ERROR"
Local sign:String = ""
If Left(StringInt1, 1) <> "-" Then
If Left(StringInt2, 1) = "-" Then
sign = "-"
StringInt2 = Right(StringInt2, Len(StringInt2)-1)
End If
Else '(Left(StringInt1, 1) = "-")
StringInt1 = Right(StringInt1, Len(StringInt1)-1)
If Left(StringInt2, 1) <> "-" Then
sign = "-"
Else '(Left(StringInt2, 1) = "-")
StringInt2 = Right(StringInt2, Len(StringInt2)-1)
End If
End If
'------------------------------------------------
Local comparison:Int = compare_StringInts(StringInt1, StringInt2)
If comparison = 1 Then
'-----------------------------------
Local multiplied_StringInt2:String[10]
multiplied_StringInt2[1] = StringInt2
For Local mSI:Int = 2 To 9
multiplied_StringInt2[mSI] = add_StringInts(multiplied_StringInt2[mSI - 1], StringInt2)
Next
'-----------------------------------
Local StringInt3:String
Local Len1:Int = Len(StringInt1)
Local Len2:Int = Len(StringInt2)
Local index:Int = Len2
Local rest:String = Left(StringInt1, Len2-1)
While index =< Len1
Local Part_from_StringInt1:String
If rest <> "0" Then
Part_from_StringInt1 = rest + Mid(StringInt1, index, 1)
Else
Part_from_StringInt1 = Mid(StringInt1, index, 1)
End If
Local TestFactor:Int = 0
Repeat
TestFactor = TestFactor + 1
If TestFactor = 10 Then Exit
Until compare_StringInts(Part_from_StringInt1, multiplied_StringInt2[TestFactor]) = 2
TestFactor = TestFactor - 1
If Part_from_StringInt1 <> multiplied_StringInt2[TestFactor] Then
rest = subtract_StringInts(Part_from_StringInt1, multiplied_StringInt2[TestFactor])
Else
rest = ""
End If
StringInt3 = StringInt3 + String(TestFactor)
index = index + 1
Wend
If Left(StringInt3, 1) = "0" Then Return sign + Right(StringInt3, Len(StringInt3)-1)
Return sign + StringInt3
'------------------------------------------
ElseIf comparison = 0 Then
Return sign + "1"
End If
Return "0" '(comparison = 2)
'######################################
End Function '(divide_StringInts)
'######################################

'######################################
Function Add_StringInts:String(StringInt1:String, StringInt2:String)
'######################################
Local Len1:Int = Len(StringInt1)
Local Len2:Int = Len(StringInt2)
Local StringInt3:String, TempInt:Int[3], Addition_to_Next:Int, digits8:Int = 8
Local sign1:String = Left(StringInt1,1)
Local sign2:String = Left(StringInt2,1)
If sign1 <> "-" Then
If sign2 <> "-" Then
sign1 = ""
Else '(If sign2 = "-")
Return subtract_StringInts(StringInt1, Right(StringInt2, Len2-1))
End If
Else '(If sign1 = "-")
If sign2 <> "-" Then
Return subtract_StringInts(StringInt2, Right(StringInt1, Len1-1))
Else '(If sign2 = "-")
sign1 = "-"
StringInt1 = Right(StringInt1, Len1-1)
Len1 = Len1 - 1
StringInt2 = Right(StringInt2, Len2-1)
Len2 = Len2 - 1
End If
End If
Repeat
TempInt[0] = Int(Mid(StringInt1, Len1 + 1 - digits8, 8))
TempInt[1] = Int(Mid(StringInt2, Len2 + 1 - digits8, 8))
TempInt[2] = TempInt[0] + TempInt[1] + Addition_to_Next
Addition_to_Next = TempInt[2] / 100000000
Local TempString:String = String(TempInt[2] Mod 100000000)
While Len(TempString) < 8
TempString = "0" + TempString
Wend
StringInt3 = TempString + StringInt3
If digits8 > Len1 And digits8 > Len2 Then Exit
digits8 = digits8 + 8
Forever
'--------------------
While Left(StringInt3,1) = "0" And Len(StringInt3) > 1
StringInt3 = Right(StringInt3, Len(StringInt3)-1)
Wend
'--------------------
If Addition_to_Next = 0 Then
If StringInt3 <> "0" Then Return sign1 + StringInt3
Return "0"
Else
Return sign1 + String(Addition_to_Next) + StringInt3
End If
'######################################
End Function '(add_StringInts)
'######################################

'######################################
Function Subtract_StringInts:String(StringInt1:String, StringInt2:String)
'######################################
Local Len1:Int = Len(StringInt1)
Local Len2:Int = Len(StringInt2)
Local StringInt3:String, TempInt:Int[3], Subtraction_to_Next:Int, digits8:Int = 8
Local sign1:String = Left(StringInt1,1)
Local sign2:String = Left(StringInt2,1)
If sign1 <> "-" Then
If sign2 <> "-" Then
If Len1 = Len2 Then
Local single_digit:Int = 1
While single_digit =< Len1
If Int(Mid(StringInt1, single_digit, 1)) <> Int(Mid(StringInt2, single_digit, 1)) Then
If Int(Mid(StringInt1, single_digit, 1)) < Int(Mid(StringInt2, single_digit, 1)) Then sign1 = "-"
Exit
End If
single_digit = single_digit + 1
Wend
End If
If sign1 = "-" Or Len1 < Len2 Then
Local MemoString:String = StringInt1
StringInt1 = StringInt2
StringInt2 = MemoString
Len1 = Len(StringInt1)
Len2 = Len(StringInt2)
sign1 = "-"
Else
sign1 = ""
End If
Else '(If sign2 = "-")
Return add_StringInts(StringInt1, Right(StringInt2, Len2-1))
End If
Else '(If sign1 = "-")
If sign2 <> "-" Then
Return add_StringInts(StringInt1, "-" + StringInt2)
Else '(If sign2 = "-")
Len1 = Len1 - 1
Len2 = Len2 - 1
StringInt1 = Right(StringInt1, Len1)
StringInt2 = Right(StringInt2, Len2)
If Len1 = Len2 Then
Local single_digit:Int = 1
While single_digit =< Len1
If Int(Mid(StringInt1, single_digit, 1)) <> Int(Mid(StringInt2, single_digit, 1)) Then
If Int(Mid(StringInt1, single_digit, 1)) < Int(Mid(StringInt2, single_digit, 1)) Then sign1 = ""
Exit
End If
single_digit = single_digit + 1
Wend
End If
If sign1 = "" Or Len1 < Len2 Then
Local MemoString:String = StringInt1
StringInt1 = StringInt2
StringInt2 = MemoString
Len1 = Len(StringInt1)
Len2 = Len(StringInt2)
sign1 = ""
End If
End If
End If
Repeat
TempInt[0] = Int(Mid(StringInt1, Len1 + 1 - digits8, 8))
TempInt[1] = Int(Mid(StringInt2, Len2 + 1 - digits8, 8))
TempInt[2] = TempInt[0] - TempInt[1] - Subtraction_to_Next
If TempInt[2] < 0 Then
If Len1 - digits8 > 0 Then
TempInt[2] = TempInt[2] + 100000000
Else
TempInt[2] = TempInt[2] + 10^Len(String(TempInt[2]))
End If
Subtraction_to_Next = 1
Else
Subtraction_to_Next = 0
End If
Local TempString:String = String(TempInt[2] Mod 100000000)
While Len(TempString) < 8
TempString = "0" + TempString
Wend
StringInt3 = TempString + StringInt3
If digits8 > Len1 And digits8 > Len2 Then Exit
digits8 = digits8 + 8
Forever
'--------------------
While Left(StringInt3,1) = "0" And Len(StringInt3) > 1
StringInt3 = Right(StringInt3, Len(StringInt3)-1)
Wend
'--------------------
If Subtraction_to_Next = 0 Then
If StringInt3 <> "0" Then Return sign1 + StringInt3
Return "0"
Else
Return sign1 + String(Subtraction_to_Next) + StringInt3
End If
'######################################
End Function '(subtract_StringInts)
'######################################
  • Zuletzt bearbeitet von BlitzMoritz am Mi, Apr 07, 2010 22:22, insgesamt 2-mal bearbeitet
 

FWeinb

ehemals "ich"

BeitragSa, März 13, 2010 19:10
Antworten mit Zitat
Benutzer-Profile anzeigen
[EDIT]: Vergesst was ich vorher geschrieben habe!

Schöne Funktionen mit Slices würde das aber denke ich noch etwas schneller gehen.

MfG
ich
"Wenn die Menschen nur über das sprächen, was sie begreifen, dann würde es sehr still auf der Welt sein." Albert Einstein (1879-1955)
"If you live each day as if it was your last, someday you'll most certainly be right." Steve Jobs

BlitzMoritz

Betreff: Erweiterung auf rationale Zahlen

BeitragMi, Apr 07, 2010 22:36
Antworten mit Zitat
Benutzer-Profile anzeigen
Nachdem ich noch einen kleinen Bug aus dem "Calculate_StringInts.bmx"-Code entfernt habe (bitte aktualisieren!), nun hier die ergänzende Datei "Calculate_StringFloats.bmx", die auf die StringInt-Funktionen zurückgreift und ihrerseits neue Funktionen bereit hält, mit der man nun auch mit rationalen (String-)Zahlen beliebiger Größe addieren, subtrahieren, multiplizieren und dividieren kann. Beim Dividieren wird mit dem dritten Argument festgelegt, wieviel Nachkommastellen berechnet werden sollen. Außerdem kommt noch die Funktion "Sqr_StringFloats()" hinzu, mit der man Wurzeln auch von rationalen Zahlen ziehen kann bzw. das Ergebnis nicht auf Ganze gerundet wird, sondern auf eine mit dem zweiten Argument festzulegende Anzahl an Nachkommastellen. Das Komma der "StringFloat"-Zahlen wird wie üblich mit einem Punkt geschrieben.
Im zweiten angefügten Demo-Code wird die Wurzel aus 2 auf 100 Nachkommastellen berechnet, außerdem mit Hilfe einer rekursiven Funktion und des Lambert-Kettenbruch-Verfahrens die Kreiszahl Pi auf 100 Nachkommastellen genau berechnet.
Hier nun zunächst die "Calculate_StringFloats.bmx"-Datei:
BlitzMax: [AUSKLAPPEN]
Include "Calculate_StringInts.bmx"

'######################################
Function Add_StringFloats:String(StringFloat1:String, StringFloat2:String)
'######################################
Local sign1:String = ""
If Left(StringFloat1, 1) = "-" Then
StringFloat1 = Right(StringFloat1, Len(StringFloat1)-1)
sign1 = "-"
End If
Local sign2:String = ""
If Left(StringFloat2, 1) = "-" Then
StringFloat2 = Right(StringFloat2, Len(StringFloat2)-1)
sign2 = "-"
End If
Local Point1:Int = Instr(StringFloat1, ".")
Local Point2:Int = Instr(StringFloat2, ".")
If Point1 = 0 Then
StringFloat1 = StringFloat1 + "."
Point1 = Len(StringFloat1)
End If
If Point2 = 0 Then
StringFloat2 = StringFloat2 + "."
Point2 = Len(StringFloat2)
End If
Local right_size1:Int = Len(StringFloat1) - Point1
Local right_size2:Int = Len(StringFloat2) - Point2
While right_size1 < right_size2
StringFloat1 = StringFloat1 + "0"
right_size1 = right_size1 + 1
Wend
While right_size2 < right_size1
StringFloat2 = StringFloat2 + "0"
right_size2 = right_size2 + 1
Wend
StringFloat1 = Left(StringFloat1, Point1-1) + Right(StringFloat1, right_size1)
StringFloat2 = Left(StringFloat2, Point2-1) + Right(StringFloat2, right_size2)
While Left(StringFloat1, 1) = "0"
StringFloat1 = Right(StringFloat1, Len(StringFloat1)-1)
Wend
While Left(StringFloat2, 1) = "0"
StringFloat2 = Right(StringFloat2, Len(StringFloat2)-1)
Wend
StringFloat1 = Add_StringInts(sign1 + StringFloat1, sign2 + StringFloat2)
If Left(StringFloat1, 1) <> "-" Then
While Len(StringFloat1) < right_size1
StringFloat1 = "0" + StringFloat1
Wend
Else 'If Left(StringFloat1, 1) = "-" Then
StringFloat1 = Right(StringFloat1, Len(StringFloat1)-1)
While Len(StringFloat1) < right_size1
StringFloat1 = "0" + StringFloat1
Wend
StringFloat1 = "-" + StringFloat1
End If
Local left_part:String = Left(StringFloat1, Len(StringFloat1) - right_size1)
If left_part <> "" Then
If left_part <> "-" Then
StringFloat1 = left_part + "." + Right(StringFloat1, right_size1)
Else
StringFloat1 = "-0." + Right(StringFloat1, right_size1)
End If
Else
StringFloat1 = "0." + Right(StringFloat1, right_size1)
End If
If Right(StringFloat1, 1) = "." Then Return StringFloat1 + "0"
Return StringFloat1
'######################################
End Function '(Add_StringFloats)
'######################################

'######################################
Function Subtract_StringFloats:String(StringFloat1:String, StringFloat2:String)
'######################################
If Left(StringFloat2,1) <> "-" Then
Return Add_StringFloats(StringFloat1, "-" + StringFloat2)
Else
Return Add_StringFloats(StringFloat1, Right(StringFloat2, Len(StringFloat2)-1))
End If
'######################################
End Function '(Subtract_StringFloats)
'######################################

'######################################
Function Multiply_StringFloats:String(StringFloat1:String, StringFloat2:String)
'######################################
Local sign:String = ""
If Left(StringFloat1, 1) <> "-" Then
If Left(StringFloat2, 1) = "-" Then
StringFloat2 = Right(StringFloat2, Len(StringFloat2)-1)
sign = "-"
End If
Else
StringFloat1 = Right(StringFloat1, Len(StringFloat1)-1)
If Left(StringFloat2, 1) <> "-" Then
sign = "-"
Else
StringFloat2 = Right(StringFloat2, Len(StringFloat2)-1)
End If
End If
Local Point1:Int = Instr(StringFloat1, ".")
Local Point2:Int = Instr(StringFloat2, ".")
If Point1 = 0 Then
StringFloat1 = StringFloat1 + "."
Point1 = Len(StringFloat1)
End If
If Point2 = 0 Then
StringFloat2 = StringFloat2 + "."
Point2 = Len(StringFloat2)
End If
Local right_size1:Int = Len(StringFloat1) - Point1
Local right_size2:Int = Len(StringFloat2) - Point2
StringFloat1 = Left(StringFloat1, Point1-1) + Right(StringFloat1, right_size1)
StringFloat2 = Left(StringFloat2, Point2-1) + Right(StringFloat2, right_size2)
While Left(StringFloat1, 1) = "0"
StringFloat1 = Right(StringFloat1, Len(StringFloat1)-1)
Wend
While Left(StringFloat2, 1) = "0"
StringFloat2 = Right(StringFloat2, Len(StringFloat2)-1)
Wend
StringFloat1 = Multiply_StringInts(StringFloat1, StringFloat2)
While Len(StringFloat1) < right_size1 + right_size2
StringFloat1 = "0" + StringFloat1
Wend
Local left_part:String = Left(StringFloat1, Len(StringFloat1) - right_size1 - right_size2 )
If left_part <> "" Then
StringFloat1 = left_part + "." + Right(StringFloat1, right_size1 + right_size2)
Else
StringFloat1 = "0." + StringFloat1
End If
If Right(StringFloat1, 1) = "." Then Return sign + StringFloat1 + "0"
Return sign + StringFloat1
'######################################
End Function '(Multiply_StringFloats)
'######################################

'######################################
Function Divide_StringFloats:String(StringFloat1:String, StringFloat2:String, Digits:Int = 16)
'######################################
Local sign2:String = ""
If Left(StringFloat2, 1) = "-" Then
sign2 = "-"
StringFloat2 = Right(StringFloat2, Len(StringFloat2)-1)
End If
Local point2:Int = Instr(StringFloat2, ".")
Local new_point:Int = 1
If point2 > 0 Then new_point = 1 + Len(StringFloat2)-point2
Local Denominator:String = Left(StringFloat2, point2 - 1) + Right(StringFloat2, Len(StringFloat2)-point2)
While Left(Denominator,1) = "0"
Denominator = Right(Denominator, Len(Denominator)-1)
Wend
Local Enumerator:String = "1"
For Local i:Int = 2 To Len(Denominator)
Enumerator = Enumerator + "0"
Next
For Local i:Int = 1 To Digits
Enumerator = Enumerator + "0"
Next
StringFloat2 = Divide_StringInts(Enumerator, Denominator)
If new_point + Len(StringFloat2) =< Len(Enumerator) Then
While new_point + Len(StringFloat2) < Len(Enumerator)
StringFloat2 = "0" + StringFloat2
Wend
StringFloat2 = sign2 + "0." + StringFloat2
Else
new_point = new_point - (Len(Enumerator)-Len(StringFloat2))
StringFloat2 = sign2 + Left(StringFloat2, new_point) + "." + Right(StringFloat2, Len(StringFloat2)-new_point)
End If
While Right(StringFloat2, 1) = "0"
StringFloat2 = Left(StringFloat2, Len(StringFloat2)-1)
Wend
Return Multiply_StringFloats(StringFloat1, StringFloat2)
'######################################
End Function '(Divide_StringFloats)
'######################################

'######################################
Function Sqr_StringFloats:String(StringFloat:String, digits:Int)
'######################################
If Left(StringFloat,1) = "-" Then Return "ERROR"
If Left(StringFloat,1) = "+" Then StringFloat = Right(StringFloat, Len(StringFloat)-1)
Local point:Int = Instr(StringFloat, ".")
Local dragged_point:Int
If Left(StringFloat,2) = "0." Then
dragged_point = 3
While Mid(StringFloat, dragged_point, 1) = "0"
dragged_point = dragged_point + 1
Wend
If dragged_point/2*2 = dragged_point Then
point = 2
StringFloat = Mid(StringFloat, dragged_point, 1) + "." + Right(StringFloat, Len(StringFloat) - dragged_point)
Else
point = 3
If dragged_point < Len(StringFloat)
StringFloat = Mid(StringFloat, dragged_point, 2) + "." + Right(StringFloat, Len(StringFloat) - dragged_point - 1)
dragged_point = dragged_point + 1
Else
StringFloat = Mid(StringFloat, dragged_point, 1) + "0."
dragged_point = dragged_point + 1
End If
End If
End If
Local left_size:Int = point-1
Local right_size:Int = Len(StringFloat)-point
If point = 0 Then
left_size = Len(StringFloat)
right_size = 2
StringFloat = StringFloat + ".00"
ElseIf right_size/2*2 <> right_size Then
StringFloat = StringFloat + "0"
right_size = right_size + 1
End If
While right_size/2 < digits
StringFloat = StringFloat + "00"
right_size = right_size + 2
Wend
Local div:String = "1"
For Local i:Int = 1 To right_size/2
div = div + "0"
Next
Local substitute_Int:String = Left(StringFloat, left_size) + Right(StringFloat, right_size)
substitute_Int = Sqr_StringInt(substitute_Int)
If dragged_point = 0 Then
If left_size/2*2 = left_size Then
StringFloat = Left(substitute_Int, left_size/2) + "." + Right(substitute_Int, Len(substitute_Int) - left_size/2)
Else
StringFloat = Left(substitute_Int, left_size/2+1) + "." + Right(substitute_Int, Len(substitute_Int) - left_size/2 - 1)
End If
Else 'If dragged_point > 0 Then
Local dp:Int = 2
While dp < dragged_point/2
substitute_Int = "0" + substitute_Int
dp = dp + 1
Wend
StringFloat = "0." + substitute_Int
End If
Return StringFloat
'######################################
End Function '(Sqr_StringFloats)
'######################################

Und nun die kleine Demo:

BlitzMax: [AUSKLAPPEN]
SuperStrict
Include "Calculate_StringFloats.bmx"
Print
Print "Sqr(2) (in Double-Size):"
Print Sqr(2)
Print "And now Sqr(2) with 100 digits:"
Print Sqr_StringFloats("2", 100)
Global MaxIteration:Int = 131
Global Iteration:Int = 0
Print
Print "Pi (in Double_Size):"
Print Pi
Print "And now Pi by Lambert-algorithmus (with 131 iterations and 100 correct digits):"
Print Divide_StringFloats("4", Lambert(),MaxIteration)
Function Lambert:String()
If Iteration < MaxIteration Then
Iteration = Iteration + 1
Local StringFloat1:String = String(Iteration + Iteration - 1)
Local StringFloat2:String = Multiply_StringInts(String(Iteration), String(Iteration))
Local StringFloat3:String = Divide_StringFloats(StringFloat2, Lambert(), MaxIteration)
Return Add_StringFloats(StringFloat1, StringFloat3)
Else
Iteration = Iteration + 1
Return String(Iteration + Iteration + 1)
End If
End Function

Neue Antwort erstellen


Übersicht BlitzMax, BlitzMax NG Codearchiv & Module

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group