n'hésitez pas à formuler des critiques quelles soient positives ou négatives, car c'est dans l'erreur qu'on progresse !
Code : Tout sélectionner
; DefineNGF - Nombre Grand Format
#NGFDim=10000
#Decimales_Defaut=0.001
Structure NGF
Longueur.w
Signe.w
Nombre.i[#NGFDim]
EndStructure
; Signes
#NGFNegatif=1
#NGFPositif=0
; Types erreur (Longueur-champ)
#NGFIndefini=-1
#NGFInfinitif=-2
#NGFDepassement=-3
#NGFNonMisEnOeuvre=-4
; Dimensions
#NGFLongueur=9
#NGFMod=1000000000
Declare.s Afficher(*Nombre.NGF) ;String
Declare NbreVersChaine(*Chaine.String,*Nombre.NGF) ;Chaine <- Nombre
Declare ChaineVersNbre(*Chaine,*Nombre.NGF) ;Chaine -> Nombre
Declare NGFNormaliser(*a.NGF) ;a = (a)
Declare NGFErreur(type,stype,*a.NGF) ;c = Err
Declare NGFCopier(*a.NGF,*b.NGF) ;b = a
Declare NGFZero(*a.NGF) ;a = 0
Declare NGFAbs(*a.NGF) ;a = |a|
Declare NGFMu10(*a.NGF,b.i,*c.NGF) ;c = a*b, |b|<10^10
Declare NGFMultiplier(*a.NGF,*b.NGF,*c.NGF);c = a*b
Declare NGFDiviser(*a.NGF,*b.NGF,*c.NGF) ;c = a/b
Declare NGFDi10(*a.NGF,b.i,*c.NGF) ;c = a/b, |b|<10^10
Declare NGFAjouter(*a.NGF,*b.NGF,*c.NGF) ;c = a+b
Declare NGFSoustraire(*a.NGF,*b.NGF,*c.NGF);c = a-b
Declare NGFCarre(*a.NGF) ;a = a*a
Declare NGFPuissance(*a.NGF,b.i,*c.NGF) ;c = a^b
Declare.i NGFPlusGrand(*a.NGF,*b.NGF,abs=0); a>b? ou |a|>|b|?
Declare.i NGFEgal(*a.NGF,*b.NGF,abs=0) ; a=b? ou |a|=|b|?
Declare.i NGFPositif(*a.NGF) ; a>=0?
Global NGF_Cache_A.NGF
Global NGF_Cache_B.NGF
Global NGF_Cache_C.NGF
Procedure.s Afficher(*Nombre.NGF) ;String
Protected n
Protected Texte.s
If *Nombre\Longueur<0
Select *Nombre\Longueur
Case #NGFIndefini
Texte="Indéfini"
Case #NGFInfinitif
Texte="Infinitif"
If *Nombre\Signe
Texte="Moins "+Texte
EndIf
Case #NGFDepassement
Texte="Dépassement"
Case #NGFNonMisEnOeuvre
Texte="Non mis en oeuvre"
EndSelect
Else
If *Nombre\Signe
Texte="-"
EndIf
n=*Nombre\Longueur
Texte+Str(*Nombre\Nombre[n])
While n>0
n-1
Texte+RSet(Str(*Nombre\Nombre[n]),#NGFLongueur,"0")
Wend
EndIf
ProcedureReturn Texte
EndProcedure
Procedure NbreVersChaine(*Chaine.String,*Nombre.NGF) ;Chaine <- Nombre
; AVERTISSEMENT! s est de type String dans cette routine!
; (Cela signifie que si x.string appèle "NbreVersChaine(x,Nombre)" la sortie sera "Debug x\s")
Protected n
Protected Texte.s
If *Nombre\Signe
Texte="-"
EndIf
n=*Nombre\Longueur
Texte+Str(*Nombre\Nombre[n])
While n>0
n-1
Texte+RSet(Str(*Nombre\Nombre[n]),#NGFLongueur,"0")
Wend
*Chaine\s=Texte
EndProcedure
Procedure ChaineVersNbre(*Chaine.String,*Nombre.NGF) ;Chaine -> Nombre
Protected n,p
Protected Texte.s
*Nombre\Signe=#NGFPositif
Texte=PeekS(@*Chaine)
n=Len(Texte)-#NGFLongueur
While n>0
*Nombre\Nombre[p]=Val(PeekS(@Texte+n,#NGFLongueur))
p+1
n-#NGFLongueur
Wend
n=Val(PeekS(@Texte,9+n))
If n<0
*Nombre\Signe=#NGFNegatif
n=-n
EndIf
*Nombre\Nombre[p]=n
*Nombre\Longueur=p
EndProcedure
Procedure NGFNormaliser(*a.NGF) ;a = (a) -a = a
; Boucle contenant les zéros (000.000.000)
If *a\Longueur>=0
While (*a\Longueur>=0) And (*a\Nombre[*a\Longueur]=0)
*a\Longueur-1
Wend
; Valeur égale à zéro? signe positif
If *a\Longueur<0
*a\Longueur=0
*a\Signe=#NGFPositif
EndIf
EndIf
EndProcedure
Procedure NGFErreur(type,stype,*a.NGF) ;c = Err
If type>=0
type=stype
EndIf
Debug "ERREUR "+Str(type)
*a\Longueur=type
EndProcedure
Procedure NGFCopier(*a.NGF,*b.NGF) ;b = a
Protected n
n=*a\Longueur
*b\Longueur=n
*b\Signe=*a\Signe
While n>=0
*b\Nombre[n]=*a\Nombre[n]
n-1
Wend
EndProcedure
Procedure NGFZero(*a.NGF) ;a = 0
*a\Longueur=0
*a\Signe=#NGFPositif
*a\Nombre[0]=0
EndProcedure
Procedure NGFAbs(*a.NGF) ;a = |a|
*a\Signe=#NGFPositif
EndProcedure
Procedure.i NGFEgal(*a.NGF,*b.NGF,abs=0)
Protected n
If n<>*b\Longueur
ProcedureReturn #False
ElseIf (abs=0) And (*a\Signe<>*b\Signe)
ProcedureReturn #False
Else
While n>=0
If *a\Nombre[n]<>*b\Nombre[n]
ProcedureReturn #False
EndIf
n-1
Wend
ProcedureReturn #True; a=b
EndIf
EndProcedure
Procedure.i NGFPlusGrand(*a.NGF,*b.NGF,abs=0) ; a>b? ou |a|>|b|?
Protected n,Difference
If abs=0
If *a\Signe<>*b\Signe
If *a\Signe=#NGFPositif
ProcedureReturn #True
Else
ProcedureReturn #False
EndIf
EndIf
Else
n=*a\Longueur
If n>*b\Longueur
ProcedureReturn #True
ElseIf n<*b\Longueur
ProcedureReturn #False
Else
While n>=0
Difference=*a\Nombre[n]-*b\Nombre[n]
If Difference>0
ProcedureReturn #True ; a>b
ElseIf Difference<0
ProcedureReturn #False ; a<b
EndIf
n-1
Wend
ProcedureReturn #False; a=b
EndIf
EndIf
EndProcedure
Procedure.i NGFPositif(*a.NGF) ; a>=0?
If *a\Signe=#NGFPositif
ProcedureReturn #True
Else
ProcedureReturn #False
EndIf
EndProcedure
Procedure NGFMu10(*a.NGF,b.i,*c.NGF) ;c = a*b, |b|<10^10
Protected n
Protected m.q
n=*a\Longueur
If n<0
NGFErreur(n,0,*c.NGF)
Else
If b=0
*c\Longueur=0
*c\Signe=#NGFPositif
*c\Nombre[0]=0
Else
If b<0
b=-b
*c\Signe=#NGFNegatif-*a\Signe
Else
*c\Signe=*a\Signe
EndIf
n=0
Repeat
m+*a\Nombre[n] * b
*c\Nombre[n]=m%#NGFMod
m/#NGFMod
n+1
Until n>*a\Longueur
If m
*c\Nombre[n]=m
Else
n-1
EndIf
*c\Longueur=n
EndIf
EndIf
EndProcedure
Procedure NGFMultiplier(*a.NGF,*b.NGF,*c.NGF) ;c = a*b
Protected la
Protected lb
Protected n
Protected s.q
Protected z.q
If (*a\Longueur<0) Or (*b\Longueur<0)
NGFErreur(*a\Longueur,*b\Longueur,*c.NGF)
Else
*c\Signe=(*a\Signe + *b\Signe)&1; parce que #NGFNegatif=1
*c\Longueur=*a\Longueur+*b\Longueur+1
For n=0 To *c\Longueur
*c\Nombre[n]=0
Next n
la=0
Repeat
lb=0
z=*b\Nombre[lb]
Repeat
s=*a\Nombre[la] * *b\Nombre[lb] + *c\Nombre[la+lb]
*c\Nombre[la+lb]=s%#NGFMod
*c\Nombre[la+lb+1]+s/#NGFMod
lb+1
Until lb>*b\Longueur
la+1
Until la>*a\Longueur
NGFNormaliser(*c)
EndIf
EndProcedure
Procedure NGFDi10(*a.NGF,b.i,*c.NGF) ;c = a/b, |b|<10^10
Protected n
Protected d.q,q.q
n=*a\Longueur
If n<0
NGFErreur(n,0,*c.NGF)
Else
If b=0
*c\Longueur=#NGFIndefini
Else
If b<0
b=-b
*c\Signe=#NGFNegatif-*a\Signe
Else
*c\Signe=*a\Signe
EndIf
Repeat
d=d*#NGFMod+*a\Nombre[n]
q=d/b
*c\Nombre[n]=q
d-q*b
n-1
Until n<0
NGFNormaliser(*c)
EndIf
EndIf
EndProcedure
Procedure NGFDiviser(*a.NGF,*b.NGF,*c.NGF) ;c = a/b
Protected n
If (*a\Longueur<0) Or (*b\Longueur<0)
NGFErreur(*a\Longueur,*b\Longueur,*c.NGF)
Else
n=*b\Longueur
If n=0
If *b\Nombre[0]=0
*c\Longueur=#NGFIndefini
Else
;Debug "Di10"
NGFDi10(*a.NGF,*b\Nombre[0],*c.NGF)
*c\Signe=-(1&(*a\Signe+*b\Signe))
EndIf
Else
If NGFPlusGrand(*b,*a,#True)
NGFZero(*c)
Else
; Hmmm... je vois pas trop
EndIf
EndIf
EndIf
EndProcedure
Procedure NGFAjouter(*a.NGF,*b.NGF,*c.NGF) ;c = a+b
Protected n
Protected s
If (*a\Longueur<0) Or (*b\Longueur<0)
NGFErreur(*a\Longueur,*b\Longueur,*c.NGF)
Else
If *a\Signe<>*b\Signe
;Debug "Soustraire"
*b\Signe=*a\Signe
NGFSoustraire(*a.NGF,*b.NGF,*c.NGF)
Else
*c\Signe=*a\Signe
If *a\Longueur<*b\Longueur
Swap *a,*b
EndIf
While n<=*a\Longueur
s+*a\Nombre[n]
If n<=*b\Longueur
s+*b\Nombre[n]
EndIf
*c\Nombre[n]=s%#NGFMod
s/#NGFMod
n+1
Wend
If s
*c\Nombre[n]=s
Else
n-1
EndIf
*c\Longueur=n
EndIf
EndIf
EndProcedure
Procedure NGFSoustraire(*a.NGF,*b.NGF,*c.NGF) ;c = a-b
Protected n
Protected s
If (*a\Longueur<0) Or (*b\Longueur<0)
NGFErreur(*a\Longueur,*b\Longueur,*c.NGF)
Else
If *a\Signe<>*b\Signe
;Debug "Ajouter"
*b\Signe=*a\Signe
NGFAjouter(*a.NGF,*b.NGF,*c.NGF)
Else
If NGFPlusGrand(*a.NGF,*b.NGF,#True)
*c\Signe=*a\Signe
Else
;Debug "swap"
Swap *a,*b
*c\Signe=#NGFNegatif-*a\Signe
EndIf
While n<=*a\Longueur
s+*a\Nombre[n]
If n<=*b\Longueur
s-*b\Nombre[n]
EndIf
If s<0
*c\Nombre[n]=s+#NGFMod
s=-1
Else
*c\Nombre[n]=s
s=0
EndIf
n+1
Wend
*c\Longueur=n-1
NGFNormaliser(*c)
EndIf
EndIf
EndProcedure
Procedure NGFCarre(*a.NGF) ;a = a*a
If *a\Longueur>=0
NGFMultiplier(*a,*a,NGF_Cache_C)
NGFCopier(NGF_Cache_C,*a)
EndIf
EndProcedure
Procedure NGFPuissance(*a.NGF,b.i,*c.NGF) ;c = a^b
Protected z=0,s,Signe
If b<0
; a^b | b<0 n'est pas mis en œuvre pour l'instant...donc pas de puissance négative
NGFErreur(#NGFNonMisEnOeuvre,0,*c.NGF)
ElseIf *a\Longueur>=0
NGFCopier(*a,NGF_Cache_A)
ChaineVersNbre(@"1",NGF_Cache_B)
If NGFPositif(*a)=#False
NGFAbs(NGF_Cache_A)
If b&1 :NGF_Cache_B\Signe=#NGFNegatif : EndIf
EndIf
While b>0
s=1<<z
If b&s
NGFMultiplier(NGF_Cache_A,NGF_Cache_B,NGF_Cache_C)
NGFCopier(NGF_Cache_C,NGF_Cache_B)
b-s
EndIf
If b
NGFCarre(NGF_Cache_A)
z+1
EndIf
Wend
NGFCopier(NGF_Cache_B,*c)
EndIf
EndProcedure
; Nom: GrandDecimal
; Description: Calcul avec des nombres infiniment grands et exacts
; Micoute le 26 mai 2012
#GDLongueurMaxi = 1000000000
#GDNbreChiffres = 9
#GDExpNull = 0
#GDExpNaN = 1
#GDExpInf = 2
Global Dim GDMultiExp.i(#GDNbreChiffres-1)
Enumeration 0
#GDArrondiInferieur ; arrondir à 0
#GDArrondiSuperieur ; écart de l'arrondi à 0
#GDArrondiPlafond ; arrondi à Infinity
#GDArrondiPlancher ; arrondi à -Infinity
#GDArrondiDemiInferieur ; arrondi au nombre entier inférieur (arrondi 0,5 à 0)
#GDArrondiDemiSuperieur ; arrondi au nombre entier supérieur (arrondi 0 à 0,5)
EndEnumeration
Structure GrandDecimal
sgn.b ; Signe
exp.i ; Multiplier par le nombre (10 ^ 9) ^ exp
taille.i ; Combien dans la mantisse
Array man.i(1) ; Mantisse
EndStructure
; Signes
#GDNegatif=1
#GDPositif=0
Declare GDAdd(*GDa.GrandDecimal, *GDb.GrandDecimal, *resultat.GrandDecimal, nGDDecimales=#PB_Default)
Declare GDSub(*GDa.GrandDecimal, *GDb.GrandDecimal, *resultat.GrandDecimal, nGDDecimales=#PB_Default)
Declare GDdeQuad(quad.q, *resultat.GrandDecimal)
Global GDModeArrondi
Global GDValeurSpecialeUnNegatif.GrandDecimal
Global Dim GDValeurSpeciale.GrandDecimal(10)
; Méthode d'initialisation (pour Tailbite)
Procedure GrandDecimal_Init()
Protected i
GDModeArrondi = #GDArrondiInferieur
GDMultiExp(0) = 1
For i = 1 To #GDNbreChiffres-1
GDMultiExp(i) = GDMultiExp(i-1)*10
Next
GDdeQuad(-1, GDValeurSpecialeUnNegatif)
For i = 0 To 10
GDdeQuad(i, GDValeurSpeciale(i))
Next
EndProcedure
GrandDecimal_Init()
; Réduit d'un certain nombre GrandDecimal sur "nGDDecimales" (arrondi ici) et normalisé (c'est à dire, pas de zéros au début et à la fin)
Procedure _GDNorm(*GD.GrandDecimal, nGDDecimales=#PB_Default)
Protected count, eman, sman, i, stmax, exp, long, rup
If (*GD\taille = 0)
; est 0, Infinity ou NaN
ProcedureReturn
EndIf
i = 0
If (nGDDecimales >= 0)
; Ce nombre est réduit
; Toutes les parties inutiles de la mantisse à 0
exp = *GD\exp - *GD\taille
While ((exp+1)*#GDNbreChiffres < -nGDDecimales)
*GD\man(i) = 0
i + 1
exp + 1
Wend
If (exp*#GDNbreChiffres < -nGDDecimales)
; Ignorer tous les points inutiles, à l'exception de la mantisse
long = *GD\man(i) / GDMultiExp(#GDNbreChiffres-nGDDecimales% #GDNbreChiffres-1)
; Si rup = 1, alors il est arrondi
Select GDModeArrondi
Case #GDArrondiInferieur
Case #GDArrondiSuperieur
rup = 1
Case #GDArrondiPlafond
If (*GD\sgn > 0)
rup = 1
EndIf
Case #GDArrondiPlancher
If (*GD\sgn < 0)
rup = 1
EndIf
Case #GDArrondiDemiInferieur, #GDArrondiDemiSuperieur
If (Mod(long,10) > 5)
rup = 1
ElseIf (Mod(long,10) = 5)
If (GDModeArrondi = #GDArrondiDemiSuperieur)
rup = 1
EndIf
EndIf
EndSelect
If (Mod(nGDDecimales,#GDNbreChiffres) = 0)
; Cas particulier, si le corps qui est important pour l'arrondissement, la mantisse est la prochaine
*GD\man(i) = 0
i + 1
If (i = *GD\taille)
If (rup = 0)
ClearStructure(*GD, GrandDecimal)
*GD\exp = #GDExpNull
ProcedureReturn
EndIf
; Pour l'arrondissement mis en place n'est pas une mantisse et doit être augmentée
ReDim *GD\man(i)
*GD\taille + 1
*GD\exp + 1
EndIf
*GD\man(i) + rup
Else
; Les nombres sans points supplémentaires seront écrits dans la mantisse (éventuellement arrondis)
*GD\man(i) = (long/10 + rup) * GDMultiExp(#GDNbreChiffres-nGDDecimales%#GDNbreChiffres)
EndIf
If (rup = 1)
; Arrondir la mantisse si le nombre est trop grand
While (*GD\man(i) = #GDLongueurMaxi)
*GD\man(i) = 0
i + 1
If (i = *GD\taille)
; Pour l'arrondissement mis en place n'est pas une mantisse et doit être augmenté
ReDim *GD\man(i)
*GD\taille + 1
*GD\exp + 1
EndIf
*GD\man(i) + 1
Wend
EndIf
EndIf
EndIf
; Si la mantisse finit par 0
eman = i
While (*GD\man(eman) = 0)
eman + 1
If (eman = *GD\taille)
; La mantisse entière est 0 -> le nombre est 0
ClearStructure(*GD, GrandDecimal)
*GD\exp = #GDExpNull
ProcedureReturn
EndIf
Wend
; Est égale à 0 au début de la mantisse
sman = 0
While (*GD\man(*GD\taille-sman-1) = 0)
sman + 1
Wend
If (eman+sman > 0)
; La mantisse doit être réduite
Protected Dim help.i(*GD\taille-eman-sman-1)
For i = eman To *GD\taille-sman-1
help(i-eman) = *GD\man(i)
Next
CopyArray(help(), *GD\man())
*GD\taille = *GD\taille-eman-sman
*GD\exp - sman
EndIf
EndProcedure
; Copie un nombre GrandDecimal et stocke le résultat dans "*resultat" si le résultat est inexact en spécifiant 'nGDDecimales'
Procedure GDCopy(*GD.GrandDecimal, *resultat.GrandDecimal, nGDDecimales=#PB_Default)
If (*GD <> *resultat)
If (*GD\man() <> #Null)
Dim *resultat\man(0)
EndIf
*resultat\exp = *GD\exp
*resultat\sgn = *GD\sgn
*resultat\taille = *GD\taille
CopyArray(*GD\man(), *resultat\man())
; CopyStructure(*GD, *resultat, GrandDecimal)
EndIf
If (nGDDecimales >= 0)
_GDNorm(*resultat, nGDDecimales)
EndIf
ProcedureReturn *resultat
EndProcedure
; Inverse un nombre GrandDecimal et stocke le résultat dans "*résultats" si le résultat est inexact en déclarant «nGDDecimales'
Procedure GDNegative(*GD.GrandDecimal, *resultat.GrandDecimal, nGDDecimales=#PB_Default)
GDCopy(*GD, *resultat, #PB_Default)
*resultat\sgn * (-1)
If (nGDDecimales >= 0)
_GDNorm(*resultat, nGDDecimales)
EndIf
ProcedureReturn *resultat
EndProcedure
; Définit le mode comment arrondir
Procedure GDModeArrondi(mode)
If (mode >= 0) And (mode <= #GDArrondiDemiSuperieur)
GDModeArrondi = mode
EndIf
EndProcedure
; Convertit une chaîne en un nombre GrandDecimal et stocke le résultat dans "*résultat"
Procedure GDdeString(str.s, *resultat.GrandDecimal)
Protected *string.Character, pos, i, cntvman, cntnman, count
ClearStructure(*resultat, GrandDecimal)
*resultat\sgn = 1
*string = @str
If (PeekC(*string) = '-')
; Nombre est négatif
*string + SizeOf(Character)
*resultat\sgn = -1
ElseIf (PeekC(*string) = '+')
*string + SizeOf(Character)
EndIf
If (CompareMemoryString(*string, @"infinity", #PB_String_NoCase, 8) = #PB_String_Equal)
; Nombre est Infinity
*resultat\exp = #GDExpInf
ProcedureReturn *resultat
ElseIf (CompareMemoryString(*string, @"nan", #PB_String_NoCase, 8) = #PB_String_Equal)
*resultat\exp = #GDExpNaN
ProcedureReturn *resultat
EndIf
str = PeekS(*string)
*string = @str
pos = FindString(str, ".", 0)
If (pos = 0)
pos = Len(str)+1
EndIf
; Nombre de mantisse après / avant le point
cntnman = Round((Len(str)-pos)/#GDNbreChiffres,1)
cntvman = Round((pos-1)/#GDNbreChiffres,1)
If (cntnman+cntvman <= 0)
*resultat\sgn = 0
*resultat\exp = #GDExpNull
ProcedureReturn *resultat
EndIf
Dim *resultat\man(cntvman+cntnman-1)
count = #GDNbreChiffres - (cntnman*#GDNbreChiffres-(Len(str)-pos))
For i = 0 To cntnman-1
; Chiffres créés derrière le point de la mantisse
*resultat\man(i) = Val(PeekS(*string+(pos+(cntnman-1-i)*#GDNbreChiffres)*SizeOf(Character), count)) * GDMultiExp(#GDNbreChiffres-count)
count = #GDNbreChiffres
Next
pos - 1
count = #GDNbreChiffres
For i = cntnman To cntnman+cntvman-1
; Chiffres créés en face du point de la mantisse
pos - #GDNbreChiffres
If (pos < 0)
count = #GDNbreChiffres+pos
pos = 0
EndIf
*resultat\man(i) = Val(PeekS(*string+pos*SizeOf(Character), count))
Next
*resultat\taille = cntnman+cntvman
*resultat\exp = cntvman
_GDNorm(*resultat, #PB_Default)
ProcedureReturn *resultat
EndProcedure
; Convertit un double en un nombre GrandDecimal et stocke le résultat dans '*resultat'
Procedure GDdeDouble(double.d, *resultat.GrandDecimal, nGDDecimales=#PB_Default)
ClearStructure(*resultat, GrandDecimal)
If IsNAN(double)
*resultat\exp = #GDExpNaN
ElseIf (double = 0)
*resultat\sgn = 0
*resultat\exp = #GDExpNull
Else
If (nGDDecimales < 0)
nGDDecimales = 15*#GDNbreChiffres-1
EndIf
GDdeString(StrD(double, nGDDecimales+1), *resultat)
EndIf
_GDNorm(*resultat, nGDDecimales)
ProcedureReturn *resultat
EndProcedure
; Convertit un Quad en un nombre GrandDecimal et stocke le résultat dans '*resultat'
Procedure GDdeQuad(quad.q, *resultat.GrandDecimal)
ClearStructure(*resultat, GrandDecimal)
If (quad < 0)
quad * (-1)
*resultat\sgn = -1
Else
*resultat\sgn = 1
EndIf
If (quad = 0)
*resultat\sgn = 0
*resultat\exp = #GDExpNull
ProcedureReturn *resultat
ElseIf (quad < #GDLongueurMaxi)
Dim *resultat\man(0)
*resultat\man(0) = quad
*resultat\exp = 1
ElseIf (quad < #GDLongueurMaxi*#GDLongueurMaxi)
Dim *resultat\man(1)
*resultat\man(0) = Mod(quad , #GDLongueurMaxi)
*resultat\man(1) = quad / #GDLongueurMaxi
*resultat\exp = 2
Else
Dim *resultat\man(2)
*resultat\man(0) = Mod(quad , #GDLongueurMaxi)
*resultat\man(1) = (quad / #GDLongueurMaxi % #GDLongueurMaxi)
*resultat\man(2) = quad / #GDLongueurMaxi / #GDLongueurMaxi
*resultat\exp = 3
EndIf
*resultat\taille = *resultat\exp
_GDNorm(*resultat, #PB_Default)
ProcedureReturn *resultat
EndProcedure
; Convertit un nombre GrandDecimal en chaîne
Procedure.s GDStr(*GD.GrandDecimal, nGDDecimales=#PB_Default)
Protected str.s
Protected i, cntdig
If (nGDDecimales >= 0)
GDCopy(*GD, *GD, nGDDecimales)
EndIf
If (*GD\sgn = -1)
str = "-"
; ElseIf (*GD\sgn = 1)
; str = "+"
EndIf
If (*GD\taille = 0)
;valeurs spéciales
Select *GD\exp
Case #GDExpNaN
ProcedureReturn "NaN"
Case #GDExpInf
ProcedureReturn str+"Infinity"
EndSelect
EndIf
cntdig = -1
If (*GD\exp <= 0)
; Nombre est inférieur à 0
If (nGDDecimales = 0)
ProcedureReturn str+"0"
EndIf
cntdig = -*GD\exp*#GDNbreChiffres
str + "0."
If (cntdig <> 0)
; Écrit des zéros qui ne sont pas stockées dans la mantisse
str + RSet("", cntdig, "0")
EndIf
EndIf
i = *GD\taille
While (#True)
i - 1
If (nGDDecimales >= 0) And (cntdig >= nGDDecimales)
; Trop de chiffres dans la chaîne -> la chaîne sera tronquée
str = PeekS(@str, Len(str)-(cntdig-nGDDecimales))
Break
EndIf
If (cntdig = -1)
If (*GD\taille-i-1 = *GD\exp)
str + "."
cntdig = #GDNbreChiffres
EndIf
Else
cntdig + #GDNbreChiffres
EndIf
If (i >= 0)
; Écrit le numéro de la mantisse (éventuellement avec des zéros comme préfixe)
If (i = *GD\taille-1) And (*GD\exp > 0)
str + Str(*GD\man(i))
Else
str + RSet(Str(*GD\man(i)), #GDNbreChiffres, "0")
EndIf
Else
; La mantisse est passé à travers
If (nGDDecimales < 0) And (cntdig <> -1)
; Si 'nGDDecimales' est manquant, nous sommes prêts
Break
EndIf
str + RSet("", #GDNbreChiffres, "0")
EndIf
Wend
ProcedureReturn str
EndProcedure
; Compare deux nombres GrandDecimal
; -1: *GDa < *GDb, 0: *GDa = *GDb, 1: *GDa > *GDb
Procedure GDCompare(*GDa.GrandDecimal, *GDb.GrandDecimal)
If ((*GDa\taille = 0) And (*GDa\exp = #GDExpNaN)) Or ((*GDb\taille = 0) And (*GDb\exp = #GDExpNaN))
; Si il y a un certain nombre de 'NaN', le résultat est 0
ProcedureReturn 0
EndIf
; Comparer Signe
If (*GDa\sgn < *GDb\sgn)
ProcedureReturn -1
ElseIf (*GDa\sgn > *GDb\sgn)
ProcedureReturn 1
ElseIf (*GDa\sgn = 0)
; Les deux nombres sont égaux à 0
ProcedureReturn 0
EndIf
; Comparer à l'infini
If (*GDa\taille = 0) And (*GDa\exp = #GDExpInf)
If (*GDb\taille = 0) And (*GDb\exp = #GDExpInf)
ProcedureReturn 0
EndIf
ProcedureReturn 1 * *GDa\sgn
ElseIf (*GDb\taille = 0) And (*GDb\exp = #GDExpInf)
ProcedureReturn (-1) * *GDa\sgn
EndIf
; Comparaison de deux nombres normaux
Protected ia, ib, cmp
cmp = *GDa\exp - *GDb\exp
; Comparaison des exposants
If (cmp < 0)
ProcedureReturn (-1) * *GDa\sgn
ElseIf (cmp > 0)
ProcedureReturn 1 * *GDa\sgn
EndIf
ia = *GDa\taille
ib = *GDb\taille
Repeat
ia - 1
ib - 1
If (ia < 0) And (ib < 0)
; Les deux chiffres sont pareils
Break
EndIf
; Un certain nombre d'extrémités, l'autre nombre est plus grand (pour +) ou moins (pour -)
If (ia < 0)
ProcedureReturn (-1) * *GDa\sgn
ElseIf (ib < 0)
ProcedureReturn 1 * *GDa\sgn
EndIf
; Comparer la Mantisse
cmp = *GDa\man(ia) - *GDb\man(ib)
If (cmp < 0)
ProcedureReturn (-1) * *GDa\sgn
ElseIf (cmp > 0)
ProcedureReturn 1 * *GDa\sgn
EndIf
ForEver
ProcedureReturn 0
EndProcedure
Procedure GDAbs(*GDa.GrandDecimal)
*GDa\Sgn=#GDPositif
EndProcedure
; Ajouter deux nombres GrandDecimal et stocke le résultat dans '*resultat'
Procedure GDAdd(*GDa.GrandDecimal, *GDb.GrandDecimal, *resultat.GrandDecimal, nGDDecimales=#PB_Default)
If ((*GDa\taille = 0) And (*GDa\exp = #GDExpNaN)) Or ((*GDb\taille = 0) And (*GDb\exp = #GDExpNaN))
; Un nombre est 'NaN'
ClearStructure(*resultat, GrandDecimal)
*resultat\exp = #GDExpNaN
ProcedureReturn *resultat
ElseIf (*GDa\taille = 0) And (*GDa\exp = #GDExpNull)
; '*GDa' est 0, le résultat est '*GDb'
ProcedureReturn GDCopy(*GDb, *resultat, nGDDecimales)
ElseIf (*GDb\taille = 0) And (*GDb\exp = #GDExpNull)
; '*GDb' est 0, le résultat est '*GDa'
ProcedureReturn GDCopy(*GDa, *resultat, nGDDecimales)
EndIf
Protected sub.GrandDecimal
; Deux différents Signe -> il est soustrait
If (*GDb\sgn = -1) And (*GDa\sgn = 1)
GDNegative(*GDb, sub, #PB_Default)
ProcedureReturn GDSub(*GDa, sub, *resultat, nGDDecimales)
ElseIf (*GDa\sgn = -1) And (*GDb\sgn = 1)
GDNegative(*GDa, sub, #PB_Default)
ProcedureReturn GDSub(*GDb, sub, *resultat, nGDDecimales)
EndIf
; Adition avec Infinity
If (*GDa\taille = 0) And (*GDa\exp = #GDExpInf)
GDCopy(*GDa, *resultat, nGDDecimales)
ProcedureReturn *resultat
ElseIf (*GDb\taille = 0) And (*GDb\exp = #GDExpInf)
GDCopy(*GDb, *resultat, nGDDecimales)
ProcedureReturn *resultat
EndIf
; Addition de deux nombres normaux
Protected sman, eman, i, ia, ib, longa, longb, ub, sgn
sgn = *GDa\sgn
; Recherche dans les plus grands exposants
sman = *GDa\exp
If (sman < *GDb\exp)
sman = *GDb\exp
EndIf
; Trouver le plus petit exposant (ou limiter 'nGDDecimales')
If (nGDDecimales < 0)
eman = *GDa\exp - *GDa\taille
If (eman > *GDb\exp - *GDb\taille)
eman = *GDb\exp - *GDb\taille
EndIf
Else
eman = -Round((nGDDecimales+1)/#GDNbreChiffres, 1)
EndIf
Protected Dim help.i(sman-eman)
i = eman
ub = 0
While (i < sman)
; Ajouter deux mantisses
longa = 0
longb = 0
ia = i + *GDa\taille - *GDa\exp
ib = i + *GDb\taille - *GDb\exp
If (ia < 0)
ElseIf (ia < *GDa\taille)
longa = *GDa\man(ia)
EndIf
If (ib < 0)
ElseIf (ib < *GDb\taille)
longb = *GDb\man(ib)
EndIf
help(i-eman) = (longa+longb+ub) % #GDLongueurMaxi
; Transfert de l'addition
ub = (longa+longb+ub) / #GDLongueurMaxi
i + 1
Wend
; Enregistrer le dernier transfert
help(sman-eman) = ub
ClearStructure(*resultat, GrandDecimal)
Dim *resultat\man(sman-eman)
CopyArray(help(), *resultat\man())
*resultat\exp = sman+1
*resultat\sgn = sgn
*resultat\taille = sman-eman+1
_GDNorm(*resultat, nGDDecimales)
ProcedureReturn *resultat
EndProcedure
; Soustrait deux nombres GrandDecimal et stocke le résultat dans '*resultat'
Procedure GDSub(*GDa.GrandDecimal, *GDb.GrandDecimal, *resultat.GrandDecimal, nGDDecimales=#PB_Default)
If ((*GDa\taille = 0) And (*GDa\exp = #GDExpNaN)) Or ((*GDb\taille = 0) And (*GDb\exp = #GDExpNaN))
; Un nombre est 'NaN'
ClearStructure(*resultat, GrandDecimal)
*resultat\exp = #GDExpNaN
ProcedureReturn *resultat
EndIf
Protected add.GrandDecimal
If (*GDa\sgn * *GDb\sgn < 1)
; Les nombres ont des signes différents, ou un nombre est 0
GDNegative(*GDb, add, #PB_Default)
ProcedureReturn GDAdd(*GDa, add, *resultat, nGDDecimales)
EndIf
; Soustraction avec Infinity
If (*GDa\taille = 0) And (*GDa\exp = #GDExpInf)
If (*GDb\taille = 0) And (*GDb\exp = #GDExpInf)
; Infinity-Infinity = NaN
ClearStructure(*resultat, GrandDecimal)
*resultat\exp = #GDExpNaN
ProcedureReturn *resultat
EndIf
GDCopy(*GDa, *resultat, nGDDecimales)
ProcedureReturn *resultat
ElseIf (*GDb\taille = 0) And (*GDb\exp = #GDExpInf)
GDNegative(*GDb, *resultat, nGDDecimales)
ProcedureReturn *resultat
EndIf
; Soustraction avec nombres normaux
Protected cmp, sman, eman, i, ia, ib, longa, longb, long, ub
; 'cmp' est le signe du nouveau nombre
cmp = GDCompare(*GDa, *GDb)
If (cmp = 0)
ClearStructure(*resultat, GrandDecimal)
*resultat\exp = #GDExpNull
ProcedureReturn *resultat
ElseIf (cmp * *GDa\sgn < 0)
; Permuter les chiffres si |*GDa|<|*GDb|
Swap *GDa, *GDb
EndIf
sman = *GDa\exp
; Trouver le plus petit exposant (ou limiter 'nGDDecimales')
If (nGDDecimales < 0)
eman = *GDa\exp - *GDa\taille
If (eman > *GDb\exp - *GDb\taille)
eman = *GDb\exp - *GDb\taille
EndIf
Else
eman = -Round((nGDDecimales+1)/#GDNbreChiffres, 1)
EndIf
Protected Dim help.i(sman-eman-1)
i = eman
ub = 0
While (i < sman)
; Soustraire deux mantisse
longa = 0
longb = 0
ia = i + *GDa\taille - *GDa\exp
ib = i + *GDb\taille - *GDb\exp
If (ia < 0)
ElseIf (ia < *GDa\taille)
longa = *GDa\man(ia)
EndIf
If (ib < 0)
ElseIf (ib < *GDb\taille)
longb = *GDb\man(ib)
EndIf
long = longa-longb-ub
If (long < 0)
; Premier nombre est inférieur au deuxième -> Transférer
long + #GDLongueurMaxi
ub = 1
EndIf
help(i-eman) = long
i + 1
Wend
ClearStructure(*resultat, GrandDecimal)
Dim *resultat\man(sman-eman-1)
CopyArray(help(), *resultat\man())
*resultat\exp = sman
*resultat\sgn = cmp
*resultat\taille = sman-eman
_GDNorm(*resultat, nGDDecimales)
ProcedureReturn *resultat
EndProcedure
; Multiplie deux nombres GrandDecimal et stocke le résultat dans '*resultat'
Procedure GDMul(*GDa.GrandDecimal, *GDb.GrandDecimal, *resultat.GrandDecimal, nGDDecimales=#PB_Default)
If ((*GDa\taille = 0) And (*GDa\exp = #GDExpNaN)) Or ((*GDb\taille = 0) And (*GDb\exp = #GDExpNaN))
; Un nombre est 'NaN'
ClearStructure(*resultat, GrandDecimal)
*resultat\exp = #GDExpNaN
ProcedureReturn *resultat
EndIf
Protected sgn
sgn = *GDa\sgn * *GDb\sgn
If ((*GDa\taille = 0) And (*GDa\exp = #GDExpInf)) Or ((*GDb\taille = 0) And (*GDb\exp = #GDExpInf))
; Multiplication avec Infinity
ClearStructure(*resultat, GrandDecimal)
*resultat\sgn = sgn
If (*resultat\sgn = 0)
; 0*Infinity = NaN
*resultat\exp = #GDExpNaN
Else
*resultat\exp = #GDExpInf
EndIf
ProcedureReturn *resultat
EndIf
; Multiplication avec nombres normaux
Protected taille, exp, stman, i, k, rsi, ub, quad.q
If (sgn = 0)
ClearStructure(*resultat, GrandDecimal)
*resultat\exp = #GDExpNull
ProcedureReturn *resultat
EndIf
stman = 0
; Nouvel Exposant et longueur de la mantisse
exp = *GDa\exp + *GDb\exp
taille = *GDa\taille + *GDb\taille
If (nGDDecimales >= 0)
; Si 'nGDDecimales' est spécifié, les parties arrières ne sont pas calculées
i = Round((nGDDecimales+2)/#GDNbreChiffres, 1)
If (taille > i+exp)
stman = taille-(i+exp)
taille = i+exp
EndIf
EndIf
If (taille <= 0)
ClearStructure(*resultat, GrandDecimal)
*resultat\exp = #GDExpNull
ProcedureReturn *resultat
EndIf
Protected Dim help.i(taille-1)
For i = 0 To *GDa\taille-1
; Aller premier nombre
ub = 0
For k = 0 To *GDb\taille-1
; Aller au deuxième nombre
rsi = i+k-stman
If (rsi >= 0)
; Multiplier les deux mantisses, Ajoutez pour le transfert précédent et mettre l'ancienne valeur dans le résultat
If (i > 0)
quad = *GDa\man(i) * *GDb\man(k) + ub + help(rsi)
Else
quad = *GDa\man(i) * *GDb\man(k) + ub
EndIf
help(rsi) = quad % #GDLongueurMaxi
ub = quad / #GDLongueurMaxi
EndIf
Next
rsi = i+*GDb\taille-stman
; Enregistrer le dernier transfert
If (rsi >= 0)
help(rsi) + ub
EndIf
Next
ClearStructure(*resultat, GrandDecimal)
Dim *resultat\man(taille-1)
CopyArray(help(), *resultat\man())
*resultat\exp = exp
*resultat\sgn = sgn
*resultat\taille = taille
_GDNorm(*resultat, nGDDecimales)
ProcedureReturn *resultat
EndProcedure
;Divise deux nombres GrandDecimal et stocke le résultat dans '*resultat'
Procedure GDDiv(*GDa.GrandDecimal, *GDb.GrandDecimal, *resultat.GrandDecimal, nGDDecimales=#PB_Default)
If ((*GDa\taille = 0) And (*GDa\exp = #GDExpNaN)) Or ((*GDb\taille = 0) And (*GDb\exp = #GDExpNaN))
; Un nombre est 'NaN'
ClearStructure(*resultat, GrandDecimal)
*resultat\exp = #GDExpNaN
ProcedureReturn *resultat
EndIf
Protected sgn
sgn = *GDa\sgn * *GDb\sgn
If (*GDa\taille = 0) And (*GDa\exp = #GDExpInf)
If (*GDb\taille = 0) And (*GDb\exp = #GDExpInf)
; Infinity/Infinity = NaN
ClearStructure(*resultat, GrandDecimal)
*resultat\exp = #GDExpNaN
ProcedureReturn *resultat
EndIf
If (sgn = 0)
sgn = *GDa\sgn
EndIf
ClearStructure(*resultat, GrandDecimal)
*resultat\exp = #GDExpInf
*resultat\sgn = sgn
ProcedureReturn *resultat
ElseIf (*GDb\taille = 0) And (*GDb\exp = #GDExpInf)
ClearStructure(*resultat, GrandDecimal)
*resultat\exp = #GDExpNull
ProcedureReturn *resultat
EndIf
If (*GDb\taille = 0) And (*GDb\exp = #GDExpNull)
; Division par 0
ClearStructure(*resultat, GrandDecimal)
*resultat\exp = #GDExpNaN
ProcedureReturn *resultat
ElseIf (*GDa\taille = 0) And (*GDa\exp = #GDExpNull)
; Diviseur est 0
ClearStructure(*resultat, GrandDecimal)
*resultat\exp = #GDExpNull
ProcedureReturn *resultat
EndIf
Protected taille, exp, i, ia, k, ka, ataille
Protected diva.q, quad.q, quadb.q, ub, qhat, qrem, double.d
; Nouvel Exposant et longueur de la Mantisse
If (nGDDecimales < 0)
nGDDecimales = ((*GDa\taille-*GDa\exp) + (*GDb\taille-*GDb\exp) + 1) * #GDNbreChiffres
EndIf
exp = *GDa\exp - *GDb\exp + 1
taille = exp+Round((nGDDecimales+2)/#GDNbreChiffres, 1)
If (taille <= 0)
ClearStructure(*resultat, GrandDecimal)
*resultat\exp = #GDExpNull
ProcedureReturn *resultat
EndIf
; Dividende nécessite nouvelle longueur
ataille = taille + *GDb\taille
If (ataille <= *GDa\taille)
ataille = *GDa\taille+1
EndIf
Dim help(taille-1)
Protected Dim diva.i(ataille-1)
Protected Dim divb.i(*GDb\taille-1)
; Normaliser diviseur (La mantisse ne peut d'abord pas commencer par 0)
k = 0
qhat = *GDb\man(*GDb\taille-1)
Repeat
qhat / 10
k + 1
Until (qhat = 0)
; Stocker dividende (normalisé ici)
ub = 0
ia = ataille-*GDa\taille-1
For i = 0 To *GDa\taille-1
quad = *GDa\man(i) * GDMultiExp(#GDNbreChiffres-k)
diva(ia) = quad % #GDLongueurMaxi + ub
ub = quad / #GDLongueurMaxi
ia + 1
Next
diva(ia) = ub
; Stocker diviseur (normalisé ici)
ub = 0
For i = 0 To *GDb\taille-1
quad = *GDb\man(i) * GDMultiExp(#GDNbreChiffres-k)
divb(i) = quad % #GDLongueurMaxi + ub
ub = quad / #GDLongueurMaxi
Next
; Démarrer le calcul
ia = ataille-1
For i = taille-1 To 0 Step -1
If (ia > 0)
diva = diva(ia) * #GDLongueurMaxi + diva(ia-1)
Else
diva = diva(ia) * #GDLongueurMaxi
EndIf
qhat = diva / divb(*GDb\taille-1)
qrem = diva % divb(*GDb\taille-1)
If (*GDb\taille >= 2)
; Diviseur mantisse a plus d'un résultat correct de la division
If (ia >= 2)
quad = qrem * #GDLongueurMaxi + diva(ia-2)
Else
quad = qrem * #GDLongueurMaxi
EndIf
quadb = divb(*GDb\taille-2) * qhat
If (quad < quadb)
qhat - 1
EndIf
EndIf
If (qhat > 0)
; Soustraire 'qhat*Divisor' de dividende
ka = ia-*GDb\taille
ub = 0
For k = 0 To *GDb\taille-1
quad = diva(ka) - divb(k) * qhat - ub
If (quad < 0)
double = Round((-quad) / #GDLongueurMaxi, 1)
ub = double
quad + ub * #GDLongueurMaxi
Else
ub = 0
EndIf
diva(ka) = quad
ka + 1
Next
If (ub > diva(ka))
; Résultat correct de la division encore, il est sorti quand la soustraction d'un nombre négatif
diva(ka) - ub
Repeat
qhat - 1
; Ajouter le diviseur au dividende à nouveau
ka = ia-*GDb\taille
ub = 0
For k = 0 To *GDb\taille-1
diva(ka) + divb(k) + ub
If (diva(ka) >= #GDLongueurMaxi)
diva(ka) - #GDLongueurMaxi
ub = 1
Else: ub = 0
EndIf
ka + 1
Next
diva(ka) + ub
Until (diva(ka) >= 0)
EndIf
; Enregistrer le résultat de la division
diva(ka) = 0
help(i) = qhat
EndIf
ia - 1
Next
ClearStructure(*resultat, GrandDecimal)
Dim *resultat\man(taille-1)
CopyArray(help(), *resultat\man())
*resultat\exp = exp
*resultat\sgn = sgn
*resultat\taille = taille
_GDNorm(*resultat, nGDDecimales)
ProcedureReturn *resultat
EndProcedure
; Calcule le résultat de la fonction exponentielle et les stocke dans '*resultat'
Procedure GDExp(*GD.GrandDecimal, *resultat.GrandDecimal, nGDDecimales)
Protected.GrandDecimal num, den, sum, GDi, div
Protected i
If (*GD\taille = 0)
Select *GD\exp
Case #GDExpNaN
GDCopy(*GD, *resultat)
Case #GDExpInf
If (*GD\sgn = 1)
; e^inf = inf
GDCopy(*GD, *resultat)
Else
; e^(-inf) = 0
ClearStructure(*resultat, GrandDecimal)
*resultat\exp = #GDExpNull
EndIf
Case #GDExpNull
; e^0 = 1
GDCopy(GDValeurSpeciale(1), *resultat)
EndSelect
ProcedureReturn *resultat
EndIf
If (*GD\sgn < 0)
; e^(-a) = 1/e^a
GDNegative(*GD, num)
GDExp(num, den, nGDDecimales)
GDDiv(GDValeurSpeciale(1), den, *resultat, nGDDecimales)
ProcedureReturn *resultat
EndIf
; e^z = somme(z^k/k!, k=0..infinity)
GDCopy(*GD, num)
GDCopy(GDValeurSpeciale(1), den)
GDCopy(GDValeurSpeciale(1), sum)
i = 1
Repeat
GDDiv(num, den, div, nGDDecimales)
If (div\taille = 0) And (div\exp = #GDExpNull)
; Les termes de la somme sont trop petits
Break
EndIf
GDAdd(sum, div, sum)
i + 1
GDMul(num, *GD, num)
GDdeQuad(i, GDi)
GDMul(den, GDi, den)
ForEver
ProcedureReturn GDCopy(sum, *resultat, nGDDecimales)
EndProcedure
; Calcule le résultat de la fonction logarithmique et le stocke dans '*resultat'
Procedure GDLog(*GD.GrandDecimal, *resultat.GrandDecimal, nGDDecimales) ; Calcule le logarithme d'un nombre
Protected.GrandDecimal num, den, qnum, qden, div, mul, sum, sumb, GDi
Protected long, multi, i, ub, GDtaille, cmp
If ((*GD\taille = 0) And (*GD\exp = #GDExpNaN)) Or (*GD\sgn < 0)
; Nombre est NaN ou négatif
ClearStructure(*resultat, GrandDecimal)
*resultat\exp = #GDExpNaN
ProcedureReturn *resultat
EndIf
If (*GD\taille = 0)
Select *GD\exp
Case #GDExpInf
; ln(inf) = inf
GDCopy(*GD, *resultat)
Case #GDExpNull
; log(0) = -inf
ClearStructure(*resultat, GrandDecimal)
*resultat\exp = #GDExpInf
*resultat\sgn = -1
EndSelect
ProcedureReturn *resultat
EndIf
If (GDCompare(*GD, GDValeurSpeciale(10)) > 0)
; Si le nombre est supérieur à 10
; log(a) = log(a/10^multi) + log(10)*multi
long = *GD\man(*GD\taille-1) / 10
While (long <> 0)
multi + 1
long / 10
Wend
GDtaille = *GD\taille
Dim num\man(GDtaille)
num\taille = GDtaille+1
num\exp = 1
num\sgn = 1
For i = GDtaille-1 To 0 Step -1
If (multi = 0)
num\man(i+1) = *GD\man(i)
Else
num\man(i+1) = *GD\man(i) / GDMultiExp(multi) + ub
ub = (*GD\man(i) % GDMultiExp(multi)) * GDMultiExp(#GDNbreChiffres-multi)
EndIf
Next
num\man(0) = ub
_GDNorm(num)
GDLog(num, sum, nGDDecimales)
multi + (*GD\exp-1) * #GDNbreChiffres
GDdeQuad(multi, mul)
GDLog(GDValeurSpeciale(10), sumb, nGDDecimales+multi/2)
GDMul(mul, sumb, sumb)
GDAdd(sum, sumb, *resultat, nGDDecimales)
ProcedureReturn *resultat
ElseIf (GDCompare(*GD, GDValeurSpeciale(2)) > 0)
; Si le nombre est supérieur à 2
; log(a) = log(a/2^multi) + log(2)*multi
long = *GD\man(*GD\taille-1)
If (long >= 8)
GDDiv(*GD, GDValeurSpeciale(8), num, nGDDecimales)
GDLog(num, sum, nGDDecimales)
GDLog(GDValeurSpeciale(2), sumb, nGDDecimales)
GDMul(GDValeurSpeciale(3), sumb, sumb)
ElseIf (long >= 4)
GDDiv(*GD, GDValeurSpeciale(4), num, nGDDecimales)
GDLog(num, sum, nGDDecimales)
GDLog(GDValeurSpeciale(2), sumb, nGDDecimales)
GDMul(GDValeurSpeciale(2), sumb, sumb)
Else
GDDiv(*GD, GDValeurSpeciale(2), num, nGDDecimales)
GDLog(num, sum, nGDDecimales)
GDLog(GDValeurSpeciale(2), sumb, nGDDecimales)
EndIf
GDAdd(sum, sumb, *resultat, nGDDecimales)
ProcedureReturn *resultat
EndIf
cmp = GDCompare(*GD, GDValeurSpeciale(1))
If (cmp > 0)
; Si le nombre est supérieur à 1
; log(a) = sum((2/(2*k-1))*((a-1)/(a+1))^(2*i-1), i=1..infinity)
GDCopy(GDValeurSpeciale(0), sum)
GDSub(*GD, GDValeurSpeciale(1), num)
GDAdd(*GD, GDValeurSpeciale(1), den)
GDMul(num, num, qnum)
GDMul(den, den, qden)
GDMul(num, GDValeurSpeciale(2), num)
i = 1
Repeat
GDdeQuad(i*2-1, GDi)
GDDiv(num, den, div, nGDDecimales)
GDDiv(div, GDi, div, nGDDecimales)
If (div\taille = 0) And (div\exp = #GDExpNull)
; Les termes de la somme sont trop petits
Break
EndIf
GDAdd(sum, div, sum)
i + 1
GDMul(num, qnum, num)
GDMul(den, qden, den)
ForEver
ProcedureReturn GDCopy(sum, *resultat, nGDDecimales)
ElseIf (cmp = 0)
; log(1) = 0
GDCopy(GDValeurSpeciale(0), *resultat)
ProcedureReturn *resultat
Else
; Si le nombre est inférieur à 1
; log(a) = -log(1/a)
GDDiv(GDValeurSpeciale(1), *GD, div, nGDDecimales)
GDLog(div, num, nGDDecimales)
GDNegative(num, *resultat, nGDDecimales)
ProcedureReturn *resultat
EndIf
EndProcedure
CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
Global a.NGF, b.NGF, Resultat.NGF, GDa.GrandDecimal, GDb.GrandDecimal, Resultat2.GrandDecimal, Resultat3.GrandDecimal
Procedure.s AjouterChaine(Argument1.s, Argument2.s, decimales.i=0)
GDdeString(Argument1, GDa)
GDdeString(Argument2, GDb)
GDAdd(GDa, GDb, Resultat2)
ProcedureReturn GDstr(Resultat2, decimales)
EndProcedure
Procedure.s SoustraireChaine(Argument1.s, Argument2.s, decimales.i=0)
GDdeString(Argument1, GDa)
GDdeString(Argument2, GDb)
GDSub(GDa, GDb, Resultat2)
ProcedureReturn GDstr(Resultat2, decimales)
EndProcedure
Procedure.s MultiplierChaine(Argument1.s, Argument2.s, decimales.i=0)
GDdeString(Argument1, GDa)
GDdeString(Argument2, GDb)
GDMul(GDa, GDb, Resultat2)
ProcedureReturn GDstr(Resultat2, decimales)
EndProcedure
Procedure.s DiviserChaine(Argument1.s, Argument2.s, decimales.i=0)
GDdeString(Argument1, GDa)
GDdeString(Argument2, GDb)
GDDiv(GDa, GDb, Resultat2, decimales)
ProcedureReturn GDstr(Resultat2, decimales)
EndProcedure
Procedure.s PuissanceChaine(Nombre$, Exposant.s) ; Calcule la puissance d'un nombre
;Procedure.s PuissanceChaine(Argument1.s, Argument2.s, decimales.i=0)
; GDdeString(Argument1, GDa)
GDdeString(Exposant, b)
; For i = 1 To Val(Argument2)
; GDMul(GDb, GDb, Resultat) ; c = a * b
; GDCopy(Resultat, Resultat2) ;b = a
; Next
ChaineVersNbre(@Nombre$, a)
NGFPuissance(a, b, Resultat)
ProcedureReturn GDStr(Resultat) ; GD
EndProcedure
Procedure.s CarreChaine(Argument$, Decimales.i=#Decimales_Defaut) ; Calcule le carré d'un nombre
GDdeString(Argument$, a)
GDMul(a, a, Resultat2)
ProcedureReturn GDstr(Resultat2, decimales)
EndProcedure
Procedure.s Remise(PrixHT$, PrixPaye$, Decimales.i=#Decimales_Defaut) ; Calculer un pourcentage de remise
Protected PrixCoutant.GrandDecimal, Total.GrandDecimal, GDc.GrandDecimal
GDdeString(PrixHT$, GDa)
GDdeString(PrixPaye$, GDb)
GDdeString("100", GDc)
GDSub(GDa, GDb, PrixCoutant) ; Prix coûtant = Prix Ht - Prix payé
GDDiv(PrixCoutant, Gda,Total); Total = Prix Coutant / Prix Ht
GDMul(Total, Gdc, Resultat2) ; Total = Prix coûtant * GDc
ProcedureReturn GDstr(Resultat2, decimales)
EndProcedure
Procedure.s Pourcentage(Argument1$, Argument2$, decimales.i=#Decimales_Defaut, Mode.i=0)
Protected Retour.GrandDecimal, GDc.GrandDecimal
GDdeString(Argument1$, GDa)
GDdeString(Argument2$, GDb)
GDdeString("100", GDc)
If mode = 0
GDDiv(GDa, GDc, Retour) ; Retour = GDa/GDc
GDMul(GDb, Retour, Resultat2) ;Resultat2 = Retour * GDb
Else
GDDiv(GDc, GDb, Retour) ; Retour = GDc/GDb
GDMul(GDa, Retour, Resultat2) ;Resultat2 = GDa * Retour
EndIf
ProcedureReturn GDstr(Resultat2, decimales)
EndProcedure
Procedure.s PourcentageAugmentation ( Argument1$, Argument2$, Decimales.i=#Decimales_Defaut)
Protected Retour.GrandDecimal, Sortie.GrandDecimal, GDc.GrandDecimal
GDdeString(Argument1$, GDa)
GDdeString(Argument2$, GDb)
GDdeString("100", GDc)
GDDiv(GDa, Gdc, Retour) ; Retour = GDa / GDc
GDMul(GDb, Retour, Sortie) ;Sortie = Retour * GDb
GDAdd(GDa, Sortie, Resultat2) ; Resultat2 = GDa + Sortie
ProcedureReturn GDstr(Resultat2, decimales)
EndProcedure
Procedure.s PourcentageDiminution (Argument1$, Argument2$, Decimales.i=#Decimales_Defaut)
Protected Retour.GrandDecimal, Sortie.GrandDecimal, GDc.GrandDecimal
GDdeString(Argument1$, GDa)
GDdeString(Argument2$, GDb)
GDdeString("100", GDc)
GDDiv(GDa, Gdc, Retour) ; Retour = GDa / GDc
GDMul(GDb, Retour, Sortie) ;Sortie = Retour * GDb
GDSub(GDa, Sortie, Resultat2) ; Resultat2 = GDa - Sortie
ProcedureReturn GDstr(Resultat2, decimales)
EndProcedure
Procedure.f Racine_N(Nbre.d, Racine.i, Decimales.i=#Decimales_Defaut) ; Calcule la racine n ème d'un nombre
Protected Dim Temporaire.d(1)
Temporaire(0)=Nbre: Temporaire(1)=Nbre/Racine
While Abs(Temporaire(1)-Temporaire(0))>Decimales
Temporaire(0)=Temporaire(1)
Temporaire(1)=((Racine-1.0)*Temporaire(1)+Nbre/Pow(Temporaire(1),Racine-1.0))/Racine
Wend
ProcedureReturn Temporaire(1)
EndProcedure
CompilerIf #PB_Compiler_IsMainFile
;/ Test Fonctions de chaînes mathématiques
InitSprite()
InitKeyboard()
InitMouse()
Enumeration
;Fenetres
#Fenetre_principale
;Actions
#Sortie
#Aucune
;Autres
EndEnumeration
Global Police =FontID(LoadFont(#PB_Any, "Arial Rounded MT", 16, #PB_Font_Bold))
Global Police2 =FontID(LoadFont(#PB_Any, "Brush Script MT", 20, #PB_Font_Italic))
Global Police3 =FontID(LoadFont(#PB_Any, "computerfont", 20, #PB_Font_Bold))
ExamineDesktops() : Global Largeur_Ecran = DesktopWidth(0) , Hauteur_Ecran = DesktopHeight(0) , Profondeur = DesktopDepth(0)
Global x, y, z, Texte.s, Titre.s = "Test Nombre Grand Format"
Largeur_Ecran-5 : Hauteur_Ecran-28
; ouvrir une fenêtre maximisée de la même taille que le bureau et sans bordure
;
Global h_Fenetre = OpenWindow(#Fenetre_principale, 0, 0, Largeur_Ecran, Hauteur_Ecran, Titre, #PB_Window_TitleBar)
;
; ouvrir un écran de la même taille que la fenêtre
;
OpenWindowedScreen(h_Fenetre, 0, 0, Largeur_Ecran, Hauteur_Ecran, 0, 0, 0, #PB_Screen_SmartSynchronization)
ClearScreen($50AA50)
StartDrawing(ScreenOutput())
;}
;- début de l'affichage
DrawingFont(Police)
DrawingMode(#PB_2DDrawing_AlphaChannel)
X = 0 : Y = 0
BackColor(Point(0,0))
ShowCursor_(1)
;- Ajouter
DrawText(X, Y, "AjouterChaine",$FFFF) : Y + TextHeight(Chr(32))
DrawText(X, Y, " 1524654654685468651656465468") : Y + TextHeight(" ")
DrawText(X, Y, "+") : Y + TextHeight(" ")
DrawText(X, Y, "546413524164316513652146132516") : Y + TextHeight(" ")
DrawText(X, Y, "------------------------------------------------------") : Y + TextHeight(" ")
DrawText(X, Y, AjouterChaine("1524654654685468651656465468", "546413524164316513652146132516")) : Y + TextHeight(Chr(32))
;- Soustraire
DrawText(X, Y, "SoustraireChaine", $FFFF) : Y + TextHeight(Chr(32))
DrawText(X, Y, " 546413524164316513652146132516") : Y + TextHeight(" ")
DrawText(X, Y, "-") : Y + TextHeight(" ")
DrawText(X, Y, " 1524654654685468651656465468") : Y + TextHeight(" ")
DrawText(X, Y, "------------------------------------------------------") : Y + TextHeight(" ")
DrawText(X, Y, SoustraireChaine("546413524164316513652146132516", "1524654654685468651656465468")) : Y + TextHeight(Chr(32))
;- Multiplier
DrawText(X, Y, "MultiplierChaine", $FFFF) : Y + TextHeight(Chr(32))
DrawText(X, Y, " 1524654654685468651656465468") : Y + TextHeight(" ")
DrawText(X, Y, "*") : Y + TextHeight(" ")
DrawText(X, Y, " 546413524164316513652146132516") : Y + TextHeight(" ")
DrawText(X, Y, "------------------------------------------------------") : Y + TextHeight(" ")
DrawText(X, Y, MultiplierChaine("1524654654685468651656465468", "546413524164316513652146132516")) : Y + TextHeight(Chr(32))
DrawText(X, Y, "65536*256 = "+MultiplierChaine("65536", "256")) : Y + TextHeight(Chr(32))
;- Diviser
DrawText(X, Y, "DiviserChaine", $FFFF) : Y + TextHeight(Chr(32))
DrawText(X, Y, " 1524654654685468651656465468") : Y + TextHeight(" ")
DrawText(X, Y, "/") : Y + TextHeight(" ")
DrawText(X, Y, " 54641352416") : Y + TextHeight(" ")
DrawText(X, Y, "------------------------------------------------------") : Y + TextHeight(" ")
DrawText(X, Y, " "+DiviserChaine("1524654654685468651656465468", "54641352416")) : Y + TextHeight(Chr(32))
DrawText(X, Y, "10/3 = "+DiviserChaine("10","3",145)) : Y + TextHeight(Chr(32))
DrawText(X, Y, "42/2.5 = "+DiviserChaine("42", "2.5",2)) : Y + TextHeight(Chr(32))
DrawText(X, Y, "1 / 7 = "+DiviserChaine("1", "7",144)) : Y + TextHeight(" ")
;- Puissance
;DrawText(X, Y, "PuissanceChaine",$FFFF) : Y + TextHeight(Chr(32))
;DrawText(X, Y, "24^2 = " + PuissanceChaine("2","24")) : Y + TextHeight(Chr(32))
;DrawText(X, Y, "50^50 = " + PuissanceChaine("50","50")) : Y + TextHeight(Chr(32))
;DrawText(X, Y, "99^99 = " + PuissanceChaine("99","99")) : Y + TextHeight(Chr(32))
;- Racine
DrawText(X, Y, "Racine",$FFFF) : Y + TextHeight(Chr(32))
DrawText(X, Y, "racine 125ème de 5642 = "+StrD(Pow(5642, 1/125),8)) : Y + TextHeight(Chr(32))
DrawText(X, Y, "Première estimation:",$C0FF) : Y + TextHeight(Chr(32))
DrawText(X, Y, "Racine_N(5642, 125) = " + StrD(Racine_N(5642,125))) : Y + TextHeight(Chr(32))
DrawText(X, Y, "Et la meilleure:",$C0FF) : Y + TextHeight(Chr(32))
DrawText(X, Y, "Racine_N(5642,125,0.00001) = "+StrD(Racine_N(5642,125,0.00001))) : Y + TextHeight(Chr(32))
DrawText(X, Y, "Racine carrée de 2 = "+StrD( Racine_N(2,2,#Decimales_Defaut),9)) : Y + TextHeight(Chr(32))
DrawText(X, Y, "Racine carrée de 3 = "+StrD( Racine_N(3,2))) : Y + TextHeight(Chr(32))
DrawText(X, Y, "Racine cubique de 27 = "+StrD( Racine_N(27,3),0)) : Y + TextHeight(Chr(32))
DrawText(X, Y, "Racine 8ème de 4 = "+StrD(Racine_N(4,8))) : Y + TextHeight(Chr(32))
;- Remise
DrawText(X, Y, "Remise",$FFFF) : Y + TextHeight(Chr(32))
DrawText(X, Y, "1 article coûte 148 euros, que j'ai payé 136,16 euros" + ", ma ristourne est de : "+Remise("148","136.16",2)+" %") : Y + TextHeight(Chr(32))
DrawText(X, Y, "1 article à 136,16 euros, je l'ai payé 133,44 euros" + ", on m'a fait une remise de : "+Remise("136.16","133.436",2)+" %") : Y + TextHeight(Chr(32))
X = Largeur_Ecran / 2 : Y = 0
;- Augmentation
DrawText(X, Y, "Augmentation",$FFFF) : Y + TextHeight(Chr(32))
DrawText(X, Y, "1370 + 5.31% = " + PourcentageAugmentation("1370","5.31",2)) : Y + TextHeight(Chr(32))
DrawText(X, Y, "136,16 + 2% = " + PourcentageAugmentation("136.16","2",2)) : Y + TextHeight(Chr(32))
;- Diminution
DrawText(X, Y, "Diminution", $FFFF) : Y + TextHeight(Chr(32))
DrawText(X, Y, "2300 - 20% = " + PourcentageDiminution("2300","20")) : Y + TextHeight(Chr(32))
DrawText(X, Y, "1840 - 2% = " + PourcentageDiminution("1840","2",2)) : Y + TextHeight(Chr(32))
;-Equivalence
DrawText(X, Y, "Equivalences",$FFFF) : Y + TextHeight(Chr(32))
DrawText(X, Y, "1% de 1234 est = à " + Pourcentage("1234","1",2)) : Y + TextHeight(Chr(32))
DrawText(X, Y, "12,34 est 1% de "+ Pourcentage("246.8","20",0,1)) : Y + TextHeight(Chr(32))
DrawText(X, Y, "20% de 1234 est = à " + Pourcentage("1234", "20",2)) : Y + TextHeight(Chr(32))
DrawText(X, Y, "246,80 est 20% de " + Pourcentage("246.8","20",0, 1)) : Y + TextHeight(Chr(32))
;- Carré
DrawText(X, Y, "CarreChaine",$FFFF) : Y + TextHeight(Chr(32))
DrawText(X, Y, "Carré de 4294967296 = "+CarreChaine("4294967296")) : Y + TextHeight(Chr(32))
Y + TextHeight(Chr(32))
Y + TextHeight(Chr(32))
DrawText(X, Y, "Carré de 1.999999 = "+CarreChaine("1.999999",6)) : Y + TextHeight(Chr(32))
DrawText(X, Y, "Carré de 2 = "+CarreChaine("2")) : Y + TextHeight(Chr(32))
;- fin d'affichage
DrawingFont(Police2)
Texte = "Pour quitter, pressez une touche ou cliquez la souris"
DrawText((Largeur_Ecran-TextWidth(Texte)) / 2, Hauteur_Ecran - 30, Texte, $FFFF)
StopDrawing()
;- gestion des événements en boucle sans fin
Global action.i = #Aucune
Repeat
Global Evenement = WindowEvent()
Select Evenement
Case #PB_Event_CloseWindow
action = #Sortie
Case 0
;
; il n'y a pas d'événement, donc faisons nos trucs graphiques
ExamineKeyboard()
If KeyboardPushed(#PB_Key_All)
action = #Sortie
EndIf
ExamineMouse()
If MouseButton(#PB_MouseButton_Left) <> 0
action = #Sortie
EndIf
If MouseButton(#PB_MouseButton_Middle) <> 0
action = #Sortie
EndIf
If MouseButton(#PB_MouseButton_Right) <> 0
action = #Sortie
EndIf
;
; et montrons les choses sur l'écran
;
FlipBuffers()
EndSelect
Until action = #Sortie
;- fermeture de l'écran & de la fenêtre en douceur
CloseScreen()
CloseWindow(#Fenetre_principale)
;}
CompilerEndIf
CompilerElse
MessageRequester("Attention", "Vous devez être en mode x86"+#CRLF$+"Ce logiciel ne fonctionne pas en 64 bits", #MB_ICONINFORMATION)
End
CompilerEndIf