BigInteger + Decimal en Visual Basic

Renaud42_ Messages postés 72 Date d'inscription dimanche 18 juin 2017 Statut Membre Dernière intervention 18 décembre 2019 - Modifié le 7 mars 2018 à 22:01
pgl10 Messages postés 380 Date d'inscription samedi 18 décembre 2004 Statut Membre Dernière intervention 29 octobre 2023 - 4 juil. 2018 à 19:38
Bonsoir,

J'ai fait une méthode pour calculer le nombre d'Euler :

''' <summary>
    ''' Calculate Euler.
    ''' </summary>
    ''' <param name="iterations">Number of iterations.</param>
    Public Shared Function CalculateEuler(Optional iterations As UInt32 = 18) As Decimal
        Dim one As BigInteger = 1
        Dim denominator As BigInteger = 2
        Dim lastmultiplier As Long = 2
        Dim result As Decimal = 2D

        For i As UInt32 = 1 To iterations
            result += BigInteger.Divide(one, denominator).ToString
            denominator *= lastmultiplier + 1
            lastmultiplier += 1
        Next

        ' Example :  2 + 1/(1*2) + 1/(1*2*3) + 1/(1*2*3*4) etc..

        Return result
    End Function


Et le problème est ici que le nombre qui va nous être retourné ici sera 2, et c'est normal car le BigInteger c'est comme un Integer, pas de virgules, donc pas de chiffres après la virgule. Cependant j'avais besoin du BigInteger sinon la variable denominator devenait trop grande pour Long.
Existe-t'il une sorte de "BigDecimal" en VB.NET pour que je puisse retourner ce nombre avec une virgule.
Parce que oui aussi j'ai essayé
result += one / denominator
, le problème ici étant que result est une variable Decimal et que BigInteger et Decimal ne sont pas compatibles. C'est pour ça qu'il me faudrait soit un BigInteger compatible avec les décimales, soit un BigDecimal.

Merci d'avance

6 réponses

Whismeril Messages postés 19025 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 19 avril 2024 656
7 mars 2018 à 23:06
Bonsoir

avant de parler de "bigdecimal"
BigInteger.Divide(one, denominator).ToString
ça c'est un string.
que tu "ajoutes" à un Decimal.
C'est pas cohérent.

Ton but c'est de calculer la valeur du nombre d'Euler ou d'afficher le texte comme ton exemple?
0
Whismeril Messages postés 19025 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 19 avril 2024 656
7 mars 2018 à 23:35
Je code généralement en C# qui est le langage .Net de base.
Et bien avec des ulong on peut aller jusqu'à 64 itérations, ce qui donne
2.7182818284590452495923189712

En VB.Net, avec le même code, on peut aller jusqu'à 18 ce qui donne
2.7182818284590452349287527284
        Dim one As Decimal = 1
        Dim denominator As ULong = 2
        Dim lastmultiplier As ULong = 2
        Dim result As Decimal = 2D

        For i As UInt32 = 1 To iterations
            result += one / denominator
            lastmultiplier += CULng(1)
            denominator *= lastmultiplier
        Next

        ' Example :  2 + 1/(1*2) + 1/(1*2*3) + 1/(1*2*3*4) etc..

        Return result


C'est une limitation de VB que je ne connaissais pas.
Cependant 18 itérations c'est déjà pas mal, on voit que le résultat change à la 16eme décimale.

Donc en partant du principe que tu veux calculer la valeur, combien d'itération veux tu faire et est ce cohérent de "l'imprécision" du type Decimal?
0
Renaud42_ Messages postés 72 Date d'inscription dimanche 18 juin 2017 Statut Membre Dernière intervention 18 décembre 2019
Modifié le 8 mars 2018 à 19:46
18 c'est ce que j'avais trouvé au début en max et c'est parce que "denominator" est trop long. C'est pour ça que j'ai utilisé BigInteger pour avoir des nombres avec plus de chiffres pour faire + d'itérations. Le problème c'est que BigInteger n'est pas considéré comme un nombre normal et leur méthode retourne un BigInteger et on ne peut pas lui faire retourner autre chose comme par exemple un Decimal.
0
Whismeril Messages postés 19025 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 19 avril 2024 656
8 mars 2018 à 19:51
Oui, mais est vraiment utile de faire plus de 18 itérations?
0
Renaud42_ Messages postés 72 Date d'inscription dimanche 18 juin 2017 Statut Membre Dernière intervention 18 décembre 2019 > Whismeril Messages postés 19025 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 19 avril 2024
11 mars 2018 à 22:26
Bah oui, c'est un programme pour essayer de calculer Euler le plus précis possible (faut que je pousse les perfs du Visual Basic au max).
0
Whismeril Messages postés 19025 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 19 avril 2024 656
7 mars 2018 à 23:45
Tu peux regarder du coté de BigRational
https://archive.codeplex.com/?p=bcl
0
Whismeril Messages postés 19025 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 19 avril 2024 656
14 mars 2018 à 07:39
Bonjour

Ok alord as tu essayé le BigRationnal que je t'ai proposé?

D'autre part, je n'arrive pas à trouver le temps de te répondre correctement.
Ce que je veux t'expliquer est long à rédiger.
Dans un premier temps, je te propose la lecture de cet article Wikipédia.
https://fr.wikipedia.org/wiki/Virgule_flottante

Si tu comprends ou connaitre déjà bien comment ça marche, alors ma phrase suivante aura un sens pour toi, sinon il faudra que tu attendes que j'ai 2 h à te consacrer.

Il est bien possible que la précision que tu cherches à obtenir est impossible, puisque les nombres "n'existent" pas en double ou même décimale, cependant je n'ai pas vérifié, cela fait parti des 2 heures dont j'ai besoin.
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
pgl10 Messages postés 380 Date d'inscription samedi 18 décembre 2004 Statut Membre Dernière intervention 29 octobre 2023 11
14 mars 2018 à 09:26
Bonjour Renaud42
En allant jusqu'au terme : 1 / (1*2*3* ... *24*25)
et sans aucun des termes suivants, alors le résultat vaut :
85351903640077042215979 / 31399210614030336000000
A bientôt, pgl10
0
pgl10 Messages postés 380 Date d'inscription samedi 18 décembre 2004 Statut Membre Dernière intervention 29 octobre 2023 11
14 mars 2018 à 11:06
Bonjour tous,
Je précise que la fraction affichée ci-dessus est la valeur exacte du résultat.
On peut aussi ajouter que :
85351903640077042215979 = 3463 x 41231 x 10997999 x 54352957
31399210614030336000000 = (2^21)(3^10)(5^6)(7^3)(11^2)x17x23
Et on peut facilement aller beaucoup plus loin, si on veut !
Cordialement, pgl10
0
Whismeril Messages postés 19025 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 19 avril 2024 656
16 mars 2018 à 22:16
Bonsoir,
j'ai un peu de temps ce soir.

Je vais commencer par une analogie.
Imagine une calculatrice qui ne peut afficher que 10 caractères, mais elle connait la notation scientifique.
On tape 9 999 999 999.
Puis on ajoute 1
Elle affiche
1.0000E+10 => Le résultat est bon, il y a 10 caractères.
On appelle aussi cette notation, un nombre à virgule flottante. On transforme un nombre en un produit, d'un petit nombre décimal et une puissance de 10.

Si on ajoute 1.
Elle affiche toujours
1.0000E+10 => Le résultat n'est plus bon
Il faut ajouter 500 000
Pour qu'elle affiche
1.0001E+10 => changement de valeur, mais résultat toujours pas bon.

Le fait d'utiliser des nombres à virgule flottantes permet d'écrire des nombres très grands (ou très petits) avec seulement 10 caractères disponibles. Mais c'est au détriment de la précision.

En informatique, un float, un double ou un décimal sont des nombres à virgule flottante, sauf qu'il sont écrits en base 2. Et de même que pour la calculatrice, il y a un nombre de bits défini pour le nombre decimal (la mantisse) et un nombre défini de bits pour la puissance de 2 (l'exposant).
Et de même que pour la calculatrice, tout ce qui est entre 10 000 000 000 et 10 000 500 000 vaut 1.0000E+10, et tout ce qui est entre 10 000 500 000 et 10 001 500 000 vaut 1.0001E+10.
Et bien un double ou un decimal ne peuvent pas définir tous les nombres existants. Du coup, quand on les ajoute on arrive pas toujours à ce qu'on espère.

Si je prends la valeur que tu voulais récupérer dans cette autre discussion
http://codes-sources.commentcamarche.net/forum/affich-10083913-recuperer-doc-stocke-sur-web-lettre-par-lettre#1
2.718281828459045235360287471352662497 'les premières décimales de ton site
2.7182818284590452349 '18 itérations et ça diverge là
2.718281828459045249' 64 itérations et ça diverge là


On peut supposer, qu'à la 18ème itération, il manque encore des membres à additionner et que trouver un résultat légèrement inférieur va dans le bon sens.

Cependant, pour 64 itérations, ça diverge avant, et en plus le résultat est supérieur au résultat attendu. Si on faisait une itération de plus on ajouterait un membre et par conséquent on s'éloignerait encore plus du résultat attendu => problème de précision de virgule flottante.
C'est pas avec de l'informatique standard que tu pourras résoudre ce problème.

Si un gars a pris la peine de faire un site juste pour donner les 1000 premières décimales, c'est justement parce que ça n'est pas simple à calculer.
0
pgl10 Messages postés 380 Date d'inscription samedi 18 décembre 2004 Statut Membre Dernière intervention 29 octobre 2023 11
4 juil. 2018 à 19:38
Bonjour Whismeril,
Voici le calcul exact de s32 = 1+1/1+1/2!+1/3!+...+1/32!
Il permet d'obtenir 20 décimales exactes pour la constante d'Euler.

Calculs arithmétiques avec des nombres rationnels de grande taille
> # constante d'Euler ( an = 1 / n! )
> a0 = 1
a0 = 1
> a1 = 1 / 1
a1 = 1
> a2 = 1 / 2
a2 = 1/2
> a3 = a2 / 3
a3 = 1/6
> a4 = a3 / 4
a4 = 1/24
> a5 = a4 / 5
a5 = 1/120
> a6 = a5 / 6
a6 = 1/720
> a7 = a6 / 7
a7 = 1/5040
> a8 = a7 / 8
a8 = 1/40320
> a9 = a8 / 9
a9 = 1/362880
> a10 = a9 / 10
a10 = 1/3628800
> a11 = a10 / 11
a11 = 1/39916800
> a12 = a11 / 12
a12 = 1/479001600
> a13 = a12 / 13
a13 = 1/6227020800
> a14 = a13 / 14
a14 = 1/87178291200
> a15 = a14 / 15
a15 = 1/1307674368000
> a16 = a15 / 16
a16 = 1/20922789888000
> a17 = a16 / 17
a17 = 1/355687428096000
> a18 = a17 / 18
a18 = 1/6402373705728000
> a19 = a18 / 19
a19 = 1/121645100408832000
> a20 = a19 / 20
a20 = 1/2432902008176640000
> a21 = a20 / 21
a21 = 1/51090942171709440000
> a22 = a21 / 22
a22 = 1/1124000727777607680000
> a23 = a22 / 23
a23 = 1/25852016738884976640000
> a24 = a23 / 24
a24 = 1/620448401733239439360000
> a25 = a24 / 25
a25 = 1/15511210043330985984000000
> a26 = a25 / 26
a26 = 1/403291461126605635584000000
> a27 = a26 / 27
a27 = 1/10888869450418352160768000000
> a28 = a27 / 28
a28 = 1/304888344611713860501504000000
> a29 = a28 / 29
a29 = 1/8841761993739701954543616000000
> a30 = a29 / 30
a30 = 1/265252859812191058636308480000000
> a31 = a30 / 31
a31 = 1/8222838654177922817725562880000000
> a32 = a31 / 32
a32 = 1/263130836933693530167218012160000000
> s1 = a0 + a1
s1 = 2
> s2 = s1 + a2
s2 = 5/2
> s3 = s2 + a3
s3 = 8/3
> s4 = s3 + a4
s4 = 65/24
> s5 = s4 + a5
s5 = 163/60
> s6 = s5 + a6
s6 = 1957/720
> s7 = s6 + a7
s7 = 685/252
> s8 = s7 + a8
s8 = 109601/40320
> s9 = s8 + a9
s9 = 98641/36288
> s10 = s9 + a10
s10 = 9864101/3628800
> s11 = s10 + a11
s11 = 13563139/4989600
> s12 = s11 + a12
s12 = 260412269/95800320
> s13 = s12 + a13
s13 = 8463398743/3113510400
> s14 = s13 + a14
s14 = 47395032961/17435658240
> s15 = s14 + a15
s15 = 888656868019/326918592000
> s16 = s15 + a16
s16 = 56874039553217/20922789888000
> s17 = s16 + a17
s17 = 7437374403113/2736057139200
> s18 = s17 + a18
s18 = 17403456103284421/6402373705728000
> s19 = s18 + a19
s19 = 82666416490601/30411275102208
> s20 = s19 + a20
s20 = 6613313319248080001/2432902008176640000
> s21 = s20 + a21
s21 = 69439789852104840011/25545471085854720000
> s22 = s21 + a22
s22 = 611070150698522592097/224800145555521536000
> s23 = s22 + a23
s23 = 1351405140967886501753/497154168055480320000
> s24 = s23 + a24
s24 = 337310723185584470837549/124089680346647887872000
> s25 = s24 + a25
s25 = 85351903640077042215979/31399210614030336000000
> s26 = s25 + a26
s26 = 1096259850353149530222034277/403291461126605635584000000
> s27 = s26 + a27
s27 = 739975398988375932899873137/272221736260458804019200000
> s28 = s27 + a28
s28 = 828772446866981044847857913441/304888344611713860501504000000
> s29 = s28 + a29
s29 = 2403440095914245030058787948979/884176199373970195454361600000
> s30 = s29 + a30
s30 = 55464002213405654539818183437977/20404066139399312202792960000000
> s31 = s30 + a31
s31 = 5587998223000619694886681981376183/2055709663544480704431390720000000
> s32 = s31 + a32
s32 = 28610550901763172837819811744646057/10525233477347741206688720486400000
> conv s32
2.71828
> enti s32*100000000000000000000
271828182845904523536
> exit

s32 est le nombre rationnel exact résultat de ce calcul.
conv s32 est sa conversion approximative en nombre flottant.
enti x est la partie entière du nombre x.
Et il est bien sûr très facile d'aller beaucoup plus loin si on veut.
Cela montre bien qu'il y a des solutions simples au problème de Renaud42.
Cordialement, pgl10
0
Rejoignez-nous