Mes factorielles sont fausses

Ici, on fait dans le petit, le LCD qui déchire sa race, on y cause même calculatrices quand on est en manque !

Modérateur : Politburo

Tipoucet
Fonctionne à 9600 bauds
Fonctionne à 9600 bauds
Messages : 3787
Enregistré le : 10 janv. 2009 13:47

Re: Mes factorielles sont fausses

Message par Tipoucet »

Bonjour,
Entièrement d'accord avec la précision suffisante des petites machines.

Mais que fait le micro-programme que mes multiplications ne font pas pour obtenir un résultat différent et "juste" ? et j'ajouterais pourquoi ?

On est habitué à des erreurs affectant les ultimes décimales affichées. Mais ces erreurs correspondent souvent à des valeurs tellement petites qu'on les accepte comme négligeables. Dans le cas de factorielles de centaines de chiffres, ces erreurs d'arrondi correspondent à des valeurs gigantesques, comme le -2E51 de ma factorielle de 49. Si pour l'utilisateur de calculette que je suis, l'erreur de mes multiplications reste anecdotique, il est possible que les constructeurs tiennent à ce que tous les chiffres montrés soient justes, d'où les efforts pour corriger mon erreur minime, qui au lieu de montrer un entier juste avant troncature par la notation scientifique, montre cet entier erroné juste avant passage en notation scientifique. Cela fait désordre. Bon c'est spéculatif.

Pour l'algorithme à l'oeuvre dans le micro-programme, j'aimerais bien le voir de mes yeux. Je vais charger en mémoire le programme du module de TI-58 :wink:

Un essai à double sens
20220213_090723.jpg
20220213_090723.jpg (29.45 Kio) Vu 3271 fois
Dominique
Avatar du membre
C.Ret
Fonctionne à 9600 bauds
Fonctionne à 9600 bauds
Messages : 3405
Enregistré le : 31 mai 2008 23:43
Localisation : N 49°22 E 6°10

Re: Mes factorielles sont fausses à 7.E-12 % près

Message par C.Ret »

Tipoucet a écrit : 13 févr. 2022 09:59Mais que fait le micro-programme que mes multiplications ne font pas pour obtenir un résultat différent et "juste" ? et j'ajouterais pourquoi ?
Sur beaucoup de machine, les calculs sont fait "en interne" sur plus de chiffres que ce que peuvent recevoir les registres mémoire. Si ton programme utilise des registres ou des variables pour recevoir les résultats intermédiaires, tu accumules donc automatiquement des erreurs à chaque fois que le résultat d'un calcul (fait en "interne") est mémorisé.

Cela se voit particulièrement bien pour la factorielle, même si le micro-code interne fait la même chose que ton code (ici une série de simples multiplications enchainées), l'erreur accumulée sera moindre du simple fait qu'il n'y a pas l'apparition des arrondis liés à l'intervention d'n registre utilisateur.

Tu peux d'ailleurs mesurer cette erreur, il suffit de modifier ton code pour qu'il arrondisse le résultat intermédiaire de chaque multiplication à 9 ou dix chiffres et tu verras l'effet sur le résultat final.

C'est d'ailleurs pour cela que le sens du calcul a un effet, car même avec la précision "interne" la limite du nombre de chiffres pris en compte dans le calcul conduit à des approximations et arrondis différents selon le sens du calcul.

D'ailleurs tu dis que l'erreur est monstrueuse. Mais non, en fait elle est tout à fait cohérente avec la limite à 12 chiffres significatifs de la machine:

62-51 = 11 c'est pas mal d'obtenir une telle précision avec seulement 12 chiffres significatifs !


C'est d'ailleurs afin d'éviter ce problème que les HP-50g et HP Prime ont un mode "entiers longs". Les multiplications sont alors faites "en interne" ou "dans le code utilisateur" sans être limitées par la représentation des nombres en mémoire.

Sur la prime 49!-49.! donne l'écart entre le calcul exact en entier long et le calcul "en précision interne", je trouve alors 4.6311E49.
On peux d'ailleurs facilement vérifier que le sens du calcul a de l'importance et changeant le sens dans lequel on effectue le produit:
HP Prime FACT 49 et précision.png
HP Prime FACT 49 et précision.png (10.49 Kio) Vu 3252 fois
Petit rappel:
Image

Donc obtenir un écart absolu de 4.6311E49 ce n'est pas une grosse erreur, c'est une erreur relative de 7.2E-12%.
Pas de quoi attenter un procès aux constructeurs de calculettes ou règles à calculs !
Modifié en dernier par C.Ret le 13 févr. 2022 15:42, modifié 1 fois.
SHARP PC-1211 PC-1360 EL-5150 PC-E500 | Commodore C=128D | Texas Instruments Ti-57LCD Ti-74BASICalc Ti-92II Ti-58c Ti-95PROCalc Ti-30XPROMathPrint | Hewlett-Packard HP-28S HP-41C HP-15C HP-Prime HP-71B | CASIO fx-602p | NUMWORKS | Graphoplex Rietz Neperlog | PockEmul | Sommaire des M.P.O. | Ma...dov'il sapone.
Tipoucet
Fonctionne à 9600 bauds
Fonctionne à 9600 bauds
Messages : 3787
Enregistré le : 10 janv. 2009 13:47

Re: Mes factorielles sont fausses

Message par Tipoucet »

Merci C.Ret. Je ne pense pas que les erreurs soient monstrueuses, c'est leur valeur qui l'est. Cela dit je me régale de vos réponses - instructives - à vous tous. Bon dimanche :D
Dominique
Avatar du membre
Schraf
Fonctionne à 1200 bauds
Fonctionne à 1200 bauds
Messages : 499
Enregistré le : 05 mars 2020 20:45
Contact :

Re: Mes factorielles sont fausses

Message par Schraf »

Si on ne cherche pas les valeurs exactes des factorielles, il y a bien sûr la formule de Stirling.

Je viens de voir qu'en 2007 une autre formule "simple" a été trouvée, je me suis empressé de la programmer en Python (adaptable facilement sur les petites machines). Il faut juste savoir que Γ(n+1) = n !

Code : Tout sélectionner

from math import pi, sqrt, exp,log10

def fact(n):
  x = n + 1			# Γ(x) = n !
  v = .5 * (log10(2 * pi) - log10(x)) + x * (log10(x + 1 / (12 * x - 1 / (10 * x))) - log10(exp(1)))
  m, e = v % 1, int(v)		# On récupère partie fractionnaire et partie entière
  return 10 ** m, e		# On a alors la mantisse et l'exposant
  
> fact(10)
(3.6287999853984587, 6)		# C'est-à-dire 10 ! ≃ 3,6287999 * 10^6 la valeur exacte est 3 628 800
> fact(100)
(9.332621544393671, 157)	# Valeur donnée par ma calculatrice NUMWORKS = 9,332621544 * 10^157
> fact(1000)
(4.023872600769742, 2567)
> fact(10000)
(2.8462596809075893, 35659)
  
J'ai écrit le programme en utilisant le log décimal pour avoir plus facilement l'exposant mais la formule utilisée sur Wikipédia utilise le log naturel.

A titre de comparaison, la formule de Stirling donne des résultats nettement moins précis :

Code : Tout sélectionner

from math import pi, sqrt, exp,log10

def fact(n):
 v = .5 * log10(2 * pi * n) + n * (log10(n) - log10(exp(1)))
 m, e = v % 1, int(v)	
 return 10 ** m, e
 
> fact(10)
(3.5986956187410364, 6)
> fact(100)
(9.32484762526894, 157)
> fact(1000)
(4.023537292034747, 2567)
> fact(10000)
(2.8462359621833295, 35659)
Avatar du membre
Schraf
Fonctionne à 1200 bauds
Fonctionne à 1200 bauds
Messages : 499
Enregistré le : 05 mars 2020 20:45
Contact :

Re: Mes factorielles sont fausses

Message par Schraf »

Version pour HP-48G, 50G :

Code : Tout sélectionner

<< 1 +  ➝ n
'.5 * (LOG(2 * π) - LOG(n)) + n  * (LOG(n + 1 / (12 * n - .1 / n)) - LOG(EXP(1)))'
EVAL DUP FP ALOG
SWAP IP >>

'FAC STO	// Mémorisation du programme dans FAC

Tests sur une HP 50g :

30 FAC
2: 3.62879998557
1: 6.

100 FAC
2: 9.3326215505
1: 157

1000 FAC
2: 4.02387267366
1: 2567

10000 FAC
2: 2.84625954472
1: 35659
Avatar du membre
C.Ret
Fonctionne à 9600 bauds
Fonctionne à 9600 bauds
Messages : 3405
Enregistré le : 31 mai 2008 23:43
Localisation : N 49°22 E 6°10

Re: Mes factorielles sont fausses

Message par C.Ret »

Version pour Ti-58 :

Code : Tout sélectionner

Lbl B ( STO 00  ×  ( CE  ×  (  1  +  (    12 × RCL 00 x²  -  ·  1 ) 1/x  )
76 12 53 42 00 65 53 24 65 53 01 85 53 01 02 65 43 00 33 75 93 01 54 35 54
000 .  .  .  .005  .  .  .  .010  .  .  .  .015  .  .  .  .020  .  .  .  .

          ÷  1 INV lnx ) log +  (  2  × PI ÷ RCL 00 ) log  ÷ 2  ) INV SBR
          55  01 22 23 54 28 85 53 02 65 89 55 43 00 54 28 55 02 54 92
          025  .  .  .  .030  .  .  .  .035  .  .  .  .040  .  .  .044

Lbl C  +  1 =  B STO 00 Int x:t RCL 00 INV Frc INV log INV SBR
76 13 85 01 95 12 42 00  59  32  43 00  22  59 22   28  92
045 .  .  .  .050  .  .   .   . 055  .   .   .  .  060 061
Usage:
n B calcule Image

n C calcule n! à partir de Image. A la fin du calcul, la Ti-58 affiche uniquement la mantisse de n!. L'exposent de dix est dans le registre t . Pressez sur la touche x><t pour le faire apparaitre.

Exemple:
1000 C affiche 4.02387259 puis une pression sur [x><t] affiche 2567.
SHARP PC-1211 PC-1360 EL-5150 PC-E500 | Commodore C=128D | Texas Instruments Ti-57LCD Ti-74BASICalc Ti-92II Ti-58c Ti-95PROCalc Ti-30XPROMathPrint | Hewlett-Packard HP-28S HP-41C HP-15C HP-Prime HP-71B | CASIO fx-602p | NUMWORKS | Graphoplex Rietz Neperlog | PockEmul | Sommaire des M.P.O. | Ma...dov'il sapone.
Répondre

Retourner vers « Tous les Pockets »