Aller au contenu

Patite question fondamentale sur chaine vers réel


Messages recommandés

Posté(e)

(setq A "16.0123456")
 (eval A)
 (distof loc)
 (distof loc 2)
 (atof loc) 

 

J'aimerais transformer la variable A en un réel et ne pas perdre les chiffres après la virgule, ni le 5ième, ni le sixième,....

Pourquoi déjà n'a-ton droit qu'à 4 chiffres significatif ? Où lire un peu là-dessus déjà ?

Car enfin, si on traite des points, on a le droit à davantage, polar, par exemple, renvoie plus de chiffres après la virgule dans les X et Y.....

 

Merci de me rafraichir un peu....

Bureau d'études dessin.

Spécialiste Escaliers

Développement - Formation

 

./__\.
(.°=°.)
Posté(e)

Salut,

 

Ne pas confondre ce qui est affiché et ce qui est conservé en mémoire:

 

_$ pi
3.14159
_$ (rtos pi 2 16)
"3.141592653589793"
_$ (setq a "16.0123456")
"16.0123456"
_$ (distof a)
16.0123
_$ (atof a)
16.0123
_$ (rtos (distof a) 2 16)
"16.01234560000000"
_$ (rtos (atof a) 2 16)
"16.01234560000000"

 

Rien n'est perdu.

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Posté(e)

On se laisse tromper par ce que renvoie la console.

Merci pour ces rappels.

 

C'est bien ce que je me disais, la valeur n'est pas perdue seulement voilà, pour la voir restituer (sous forme de texte donc), il faut faire appel à RTOS et bien le régler (nombre de chiffre après la virgule).

 

Mais si je prends un dessin avec cette foutue variable DIMZIN à 0 (y en a plein qui tournent en Europe :cool: ), RTOS me renvoie

 "16.01234560000000"

 

Pas très joli à afficher.

 

Sais-tu comment font les anglo-saxons pour maximiser le nombre de chiffres significatifs (16 je crois au max) sans pour autant afficher les zéros de fin de chaîne s'ils existent ?

Bureau d'études dessin.

Spécialiste Escaliers

Développement - Formation

 

./__\.
(.°=°.)
Posté(e)

avec DIMZIN justement :

_$ (setvar 'dimzin 0)
0
_$ (rtos pi 2 16)
"3.141592653589793"
_$ (rtos (distof a) 2 16)
"16.01234560000000"
_$ (setvar 'dimzin 8)
8
_$ (rtos pi 2 16)
"3.141592653589793"
_$ (rtos (distof a) 2 16)
"16.0123456"

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Posté(e)

Oui, c'est ça : ils prennent le contrôle de DIMZIN s'il veulent ce résultat, les anglish.

Je cherchais une solution sans prise de contrôle de variable.

 

Remarque, si vraiment c'est nécessaire, je peux faire tout bêtement :

 (vl-string-trim "0" a)

 

Ok merci.

Bureau d'études dessin.

Spécialiste Escaliers

Développement - Formation

 

./__\.
(.°=°.)
Posté(e)

Salut,

 

Les nombres réels en AutoLISP sont ce qu'on appelle en informatique des nombres à "virgule flottante" en "double précision" (souvent appelés 'doubles'), c'est à dire qu'ils sont codés sur 64 bits (pour plus de précision voir ici).

 

La conversion entre base 10 et base 2 peut générer des imprécisions dues au fait que le nombre de bits est limité (ici à 64). Par exemple 0.625 peut être exprimé avec exactitude en base 2 :

0.625 = 0.5 + 0.125 = 2^-1 + 2^-3

Par contre 0.01 ne peut pas être exprimé avec exactitude en base 2 même avec un très grand nombre de bits et c'est le cas pour la plupart des nombres réels.

Donc quand on entre 0.01, l'ordinateur n'en conserve qu'une approximation (très précise quand même).

On considère que les 'doubles' ont 15 (ou 16 suivant les auteurs) chiffres significatifs après la virgule, mais ce nombre diminue quand on utilise des grands nombre (la mémoire allouée à la partie entière n'est plus disponible pour la partie décimale).

 

Mais cette imprécision peut augmenter lors de calculs notamment avec l'addition et la soustraction. Si on ajoute 100000 fois 0.01, on n'obtient pas exactement 100 :

_$ (setq x 0)

0

_$ (rtos (repeat 100000 (setq x (+ x 0.01))) 2 16)

"999.9999999992356"

_$ (rtos (* 0.01 100000) 2 16)

"1000.000000000000"

 

Autre exemple avec la soustraction :

_$ (= 0.01 (- 3.0 2.99))

nil

_$ (rtos (- 3.0 2.99) 2 16)

"0.0099999999999998"

 

et, bien sûr c'est pire avec des grands nombres :

_$ (rtos (- 123456789.0 123456788.99) 2 16)

"0.0100000053644180"

 

Donc en pratique, quand on compare des nombres réels en LISP (mais c'est valable pour tous les langages de programmation) il faut le faire avec une tolérance.

Personnellement, j'ai pour habitude d'utiliser 1e-9 avec laquelle je n'ai jamais été pris en défaut tout en conservant une précision plus que raisonnable (un micron pour un kilomètre).

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Posté(e)
c'est un vieux discours que je tiens depuis des lustres

et je continue à prêcher dans le désert.

 

amicalement

 

Mon cher Didier, non, tu ne prêches pas dans le désert (avec tes chameaux.) Je suis sensible à ce discours. Je me souviens même d'une conversation assez récente sur une bizarrerie de calcul. Et tu en étais ! Mias cela parlait d'entiers. On touchait du doigt le problème des entiers longs.

 

Je voulais juste me rassurer sur les moyens de sortir de l'ombre des valeurs après la virgule c'est bien réexpliqué ci-dessus. RTOS me convient moyen pour mon problème mais il n'y a bien que cette solution.

 

Oui, c'est évident pour les 16 chiffres, il y a une différence quand il y a une importante partie entière.

 

J'avais même créé, du temps de mes débuts les fonctions suivantes:

Elles vérifient pour l'une qu'un chiffre et pour l'autre qu'un point valent presque zéro à ze ou n près respectivement. Je pense que tout le monde l'a déjà fait.

 

(defun killzero (ki ze / ans ans2);(setq ki 100 ze 2)
 (setq ans 1)  
 (if (         (repeat ze (/ 1.0 (setq ans (* 10 ans)))))
   0.0    ans2    ))

;;;(killzeropt '(0 7 0.00000005) 4)

(defun killzeropt (pti n / )
 (cond((= (length pti) 2) (list (killzero (car  pti) n) (killzero (cadr  pti) n)))
      ((= (length pti) 3) (list (killzero (car  pti) n) (killzero (cadr  pti) n) (killzero (caddr pti) n)))
            ))

Bureau d'études dessin.

Spécialiste Escaliers

Développement - Formation

 

./__\.
(.°=°.)
Posté(e)

Un équivalent de killzero qui fonctionne sur les nombres, les points, les listes de points, etc.

 

(defun truezero	(num fuzz)
 (if (listp num)
   (mapcar '(lambda (x) (truezero x fuzz)) num)
   (if	(      0.0
     num
   )
 )
)

 

_$ (truezero 0.00005 0.0001)

0.0

_$ (truezero '((12.0 1.5e-12 0.0) (15.2 -2.4e-13 6.5e-10)) 1e-9)

((12.0 0.0 0.0) (15.2 0.0 0.0))

 

Ou, plus générique une fonction round:

 

(defun round (num prec)
 (if (zerop (setq prec (abs prec)))
   num
   (* prec (fix ((if (minusp num) - +) (/ num prec) 0.5)))
 )
)

 

_$ (round pi 0.0001)

3.1416

_$ (round 15.2 1)

15

_$ (round 13160.92 50)

13150

 

Et pour les points, listes de points, etc.

 

(defun round-list (lst prec)
 (if (listp lst)
   (mapcar '(lambda (x) (round-list x prec)) lst)
   (round lst prec)
 )
)

 

_$ (round-list '((228.703 255.527 0.0) (96.8073 409.166 0.0)) 0.1)

((228.7 255.5 0.0) (96.8 409.2 0.0))

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Créer un compte ou se connecter pour commenter

Vous devez être membre afin de pouvoir déposer un commentaire

Créer un compte

Créez un compte sur notre communauté. C’est facile !

Créer un nouveau compte

Se connecter

Vous avez déjà un compte ? Connectez-vous ici.

Connectez-vous maintenant
×
×
  • Créer...

Information importante

Nous avons placé des cookies sur votre appareil pour aider à améliorer ce site. Vous pouvez choisir d’ajuster vos paramètres de cookie, sinon nous supposerons que vous êtes d’accord pour continuer. Politique de confidentialité