Tramber Posté(e) le 25 novembre 2010 Posté(e) le 25 novembre 2010 (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 ./__\. (.°=°.)
(gile) Posté(e) le 25 novembre 2010 Posté(e) le 25 novembre 2010 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
Tramber Posté(e) le 25 novembre 2010 Auteur Posté(e) le 25 novembre 2010 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 ./__\. (.°=°.)
(gile) Posté(e) le 25 novembre 2010 Posté(e) le 25 novembre 2010 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
Tramber Posté(e) le 25 novembre 2010 Auteur Posté(e) le 25 novembre 2010 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 ./__\. (.°=°.)
didier Posté(e) le 26 novembre 2010 Posté(e) le 26 novembre 2010 coucou tu te fourvoies en pensant que la précision est à seize chiffres significatifs. le calcul est faux dès la onzième. c'est un vieux discours que je tiens depuis des lustreset je continue à prêcher dans le désert. amicalement Éternel débutant... Mon site perso : Programmer dans AutoCAD
(gile) Posté(e) le 26 novembre 2010 Posté(e) le 26 novembre 2010 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^-3Par 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
Tramber Posté(e) le 26 novembre 2010 Auteur Posté(e) le 26 novembre 2010 c'est un vieux discours que je tiens depuis des lustreset 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 ./__\. (.°=°.)
(gile) Posté(e) le 26 novembre 2010 Posté(e) le 26 novembre 2010 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
Messages recommandés
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 compteSe connecter
Vous avez déjà un compte ? Connectez-vous ici.
Connectez-vous maintenant