OVH Cloud OVH Cloud

entier par défaut = mauvais résultat

18 réponses
Avatar
PurL
Salut,

Je sais que par défaut, quand le compilateur (à l'exécution) à besoin de
variables intermédiaires pour effectuer une ligne de calcul, celles-ci sont
de type int. Ce qui parfois (meme tres souvent quand il s'agit de divisions)
introduit de mauvais résultats. Comment faire pour forcer le compilateur
SANS modifier le code (par option de compilation ou autre) à trouver le bon
resultat ?

Ex :

float a = 5 / 3; //a vaut 1 alors qu'il devrait valoir 1.6667

Astuces pour obtenir le bon résultat :

float a = (float)5 / 3;

ou encore :

float a = 5.0 / 3;

Mais pour un utilisateur lambda, quand il rentre 5 / 3 et qui voit un
resultat de 1, il fait un bond sur sa chaise :))
Et je vais pas lui dire qu'il faut mettre 5.0 pour que ca marche :) (les
utilisateurs finaux ne sont pas informaticiens)

Comment faire pour que 5 / 3 soit égale à 1.6667 ?

Merci pour votre aide,

PurL

8 réponses

1 2
Avatar
adebaene
PurL wrote:

Et quand il tape return 5 / 3 (dans une fonction qui retourne un
float); il

aimerait avoir 1.6667 et non pas 1, et je le comprends.
En supposant que le langage fasse ce que tu voudrais, comment tu ferais

pour récupérer le quotient d'une division?

Arnaud

Avatar
kanze
PurL wrote:
Desole, 5 et 3 sont des entiers.


C'est ce que je dis, par défaut le compilateur s'il peut
mettre en int il le fait.


Pas du tout. C'est toi qui a mis des entiers, non le
compilateur.

Mais dans "float a = 5;", a est un
float et est egal à 5, donc 5 est bien codé sous le format
d'un float et non d'un int.


a est un float. 5 reste un entier. Après la ligne que tu as
écris, a vaut 5.0F, non 5, à cause de la conversion implicite.

Sinon comment veux-tu que 5.0 / 3 fonctionne...


5.0 est un double. Il n'y a pas de surcharge de / avec un
double et un int, donc le int est converti d'abords
implicitement en double. Le resultat est un double, converti
par apres implicitement en float si tu fais

float a = 5.0/3;


Je comprend tout ça.

Ce que je trouve bizzare, c'est que "qqch" (le compilateur ?)
devrait voir qu'il faut transformer 5 et 3 en double pour
avoir un resultat correct.


Quel est le resultat correct ? Si tu considère le résultat en
prenant sur l'ensemble des réels, un résultat correct n'est pas
possible, parce qu'on n'a pas de type réel sur l'ordinateur.
Quelque soit le type que tu utilises, il y a un arrondi ou une
troncation.

Comment forcer l'apel avec les arguments de type double meme
si le compilateur veut utilisé celui avec les int ?


En lui donnant des argments de type double.

Je pense etre clair !
Je veux que a vaux 1.6667 quand je fais : float a = 5 / 3;




En fait, a ne vaudrait jamais 1.6667 ; cette valeur n'est pas
représentable dans l'ordinateur. (C'est vrai au moins pour les
ordinateurs courants.)

Pourquoi veux-tu qu'un "un utilisateur lambda non
informaticien" entre du code que tu ne verifies meme pas?


L'appli finale permet à l'utilisateur de faire du calcul
supplémentaire sur des données.
L'utilisateur écrit son code en C++ (en général, ca se limite
à des calculs mathématiques et l'utilisation de if, for, ...)

Par analogie, Excel utilise VB pour faire ces macro, mon appli
utilise le C pour que l'utilisateur manipule ses données.

Tout le code tapé par l'utilisateur est mis dans un .CPP pour
former une DLL appelée par l'appli principale.

Et quand il tape return 5 / 3 (dans une fonction qui retourne
un float); il aimerait avoir 1.6667 et non pas 1, et je le
comprends. Dans le meme style voir que le resultat de "5 / 3 *
2.5" est différent de 2.5 * 5 / 3" est quelque peu déroutant.


Donc, le C++ ne semble pas indiquer pour ce genre de chose. Pour
écrire quoique ce soit en C++, il faut comprendre les types. Or,
j'imagine ici ce qu'il te faut, c'est un langage sans type, qui
traite tout comme un double (ou comme un rationnel, ou comme un
type à précision étendue -- parce qu'il y a pas mal de pièges
avec double aussi).

Les seules surcharges que tu peux definir doivent avoir au
moins un parametres n'etant pas un type de base.


Pas d'autres solutions ?
Je vais pas changer de langage pour si peu...


Pour ce que tu as à faire, ça me semble tout à fait indiqué. Il
n'a jamais été le but de C++ d'être un langage « interactif ».

--
James Kanze GABI Software http://www.gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34



Avatar
Loïc Joly
PurL wrote:

Je pense etre clair !
Je veux que a vaux 1.6667 quand je fais : float a = 5 / 3;




En fait, si on réécrit ça sous forme de fonction :

float divise(float, float); // 1
int divise(int, int); // 2

Tu voudrais que
float a = divise(5,3);

appelle 1 et non pas 2, c'est à dire que la surcharge soit résolue en
tenant compte non seulement du type des arguments mais aussi du type de
retour. Ca n'est pas une notion existante en C++.

--
Loïc



Avatar
PurL
int divise(int, int); // 2


Je n'ai pas besoin de celle-ci puisque que tu appelles
float a = divise(6.0 / 2.0), le resultat sera le meme que si tu appelles
float a = divise(6 / 2);
Qui peut le plus, peut le moins c-a-d le float sachant gérer les nombres à
virgules sait, a fortiori, gérer les nombres sans virgules (c-a-d avec une
partie décimale nulle)

PurL

Avatar
PurL
Quel est le resultat correct ? Si tu considère le résultat en
prenant sur l'ensemble des réels, un résultat correct n'est pas
possible, parce qu'on n'a pas de type réel sur l'ordinateur.
Quelque soit le type que tu utilises, il y a un arrondi ou une
troncation.


c'est évident, mais je vais pas demandé à l'utilisateur d'utiliser un
boulier c-a-d que la précision d'un ordinateur sur les réel me suffit plus
que largement...

En fait, a ne vaudrait jamais 1.6667 ; cette valeur n'est pas
représentable dans l'ordinateur. (C'est vrai au moins pour les
ordinateurs courants.)


on est d'accord mais là n'est pas le pb.

Donc, le C++ ne semble pas indiquer pour ce genre de chose. Pour
écrire quoique ce soit en C++, il faut comprendre les types. Or,
j'imagine ici ce qu'il te faut, c'est un langage sans type, qui
traite tout comme un double (ou comme un rationnel, ou comme un
type à précision étendue -- parce qu'il y a pas mal de pièges
avec double aussi).


Effectivement, y'a des regles a respecté pour le source, je leur ai déjà
fait digirer le fait qu'il fallait mettre un ";" a chaque fin d'instruction
et terminer leur fonction/calcul par un "return" de leur résultat. C'est pas
souple, mais une fois assimiler, ce n'est pas le pérou à appliquer. Par
contre devoir mettre un ".0" derriere chaque nombre entier qu'ils écriront,
c'est plus lourd...

De quels autres pièges parles-tu au sujet des doubles ?

Pour ce que tu as à faire, ça me semble tout à fait indiqué. Il
n'a jamais été le but de C++ d'être un langage « interactif ».


mouai, je garde encore espoir...
Et puis je ne suis embeter que pour la division...

PurL

Avatar
kanze
PurL wrote:
Quel est le resultat correct ? Si tu considère le résultat
en prenant sur l'ensemble des réels, un résultat correct
n'est pas possible, parce qu'on n'a pas de type réel sur
l'ordinateur. Quelque soit le type que tu utilises, il y a
un arrondi ou une troncation.


c'est évident, mais je vais pas demandé à l'utilisateur
d'utiliser un boulier c-a-d que la précision d'un ordinateur
sur les réel me suffit plus que largement...

En fait, a ne vaudrait jamais 1.6667 ; cette valeur n'est
pas représentable dans l'ordinateur. (C'est vrai au moins
pour les ordinateurs courants.)


on est d'accord mais là n'est pas le pb.


D'accord. Dans la mésure où on se comprend. Parce que le fait
que 5 / 3 donne 1, c'est du même genre : on travaille avec les
entiers, et le résultat est un entier. Ce qui limite la
précision pas mal.

Donc, le C++ ne semble pas indiquer pour ce genre de
chose. Pour écrire quoique ce soit en C++, il faut
comprendre les types. Or, j'imagine ici ce qu'il te faut,
c'est un langage sans type, qui traite tout comme un double
(ou comme un rationnel, ou comme un type à précision étendue
-- parce qu'il y a pas mal de pièges avec double aussi).


Effectivement, y'a des regles a respecté pour le source, je
leur ai déjà fait digirer le fait qu'il fallait mettre un ";"
a chaque fin d'instruction et terminer leur fonction/calcul
par un "return" de leur résultat. C'est pas souple, mais une
fois assimiler, ce n'est pas le pérou à appliquer. Par contre
devoir mettre un ".0" derriere chaque nombre entier qu'ils
écriront, c'est plus lourd...

De quels autres pièges parles-tu au sujet des doubles ?


Le fait qu'il ne modèle pas très bien les réels. Des choses
comme le fait que l'addition n'est pas associative, par exemple.
Si les expressions sont simple, et toutes les valeurs ont à peu
près le même ordre de grandeur, il se peut que tu t'en tires
sans trop de problèmes, mais l'arithmétique flottant est un
domaine en soi.

Maintenant, si le but est simplement de pouvoir compiler avec un
compilateur C++ quelque chose précisée par l'utilisateur, je
verais bien un espèce de préprocesseur, qui génèrera des
declarations des variables, convertira les constantes numérique
en double, etc.

Pour ce que tu as à faire, ça me semble tout à fait indiqué. Il
n'a jamais été le but de C++ d'être un langage « interactif ».


mouai, je garde encore espoir...
Et puis je ne suis embeter que pour la division...


Si tu cherches à permettre à tes utilisateurs d'écrire du C++
directement, tu cherches des problèmes.

--
James Kanze GABI Software http://www.gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


Avatar
Alain Naigeon
a écrit dans le message news:


D'accord. Dans la mésure où on se comprend. Parce que le fait
que 5 / 3 donne 1, c'est du même genre : on travaille avec les
entiers, et le résultat est un entier. Ce qui limite la
précision pas mal.

Je ne comprend pas tout à fait ta réponse : les 2 divisions,
entière et réelle, me semblent d'une nature différente, ce
n'est pas seulement une question de précision.
Ou alors, il devrait exister une fonction renvoyant le reste
réel d'une division réelle de deux réels ;-)
Les deux aspects, bien que différents, sont liés : on sait
bien que le reste d'une division réelle sur une machine
concrète n'est pas nul, mais, précisément, pour modéliser
l'opération mathématique, on convient qu'il l'est dès lors
qu'il ne dépasse pas un epsilon.
Tandis qu'avec la divison entière, on se garde bien de le
"forcer" à zéro :-)

--

Français *==> "Musique renaissance" <==* English
midi - facsimiles - ligatures - mensuration
http://anaigeon.free.fr | http://www.medieval.org/emfaq/anaigeon/
Alain Naigeon - - Strasbourg, France
Avatar
PurL
Maintenant, si le but est simplement de pouvoir compiler avec un
compilateur C++ quelque chose précisée par l'utilisateur, je
verais bien un espèce de préprocesseur, qui génèrera des
declarations des variables, convertira les constantes numérique
en double, etc.


Oui, j'ai pensé à cette solution.
De parser le code pour le corriger/adapter/modifier pour la compilation.
Je le fais d'ailleurs déjà un peu par obligation pour mettre en forme
certaines variables qui viennent de l'extérieure et que l'utilisateur veut
utiliser dans son code.
Mais je m'attendais à une solution plus simple du style rajouter sur la
ligne de commannde du compilateur une option qui le force à considérer tous
les nombres comme réel...

PurL

1 2