Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

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

10 réponses

1 2
Avatar
Jean-Marc Bourguet
"PurL" writes:

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.


Drole de vision des choses: le type du resultat d'un calcul depend des
arguments.

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 ?


Rien de standard et je n'ai jamais rien vu dans le genre. Changer de
langage?

Ex :

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


Les arguments de / sont des entiers donc le resultat est entier.

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)


Je ne vois pas pourquoi tu laisses des utilisateurs finaux non
programmeurs faire des choses sans les verifier. Faudrait donner un
peu plus de contexte pour qu'on puisse te proposer des solutions.

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org

Avatar
PurL
Drole de vision des choses: le type du resultat d'un calcul depend des
arguments.


Je crois pas nan...

Ex :

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


Les arguments de / sont des entiers donc le resultat est entier.


Non, les arguments de / ne sont pas QUE des int, y'a des surchages !
Sinon comment veux-tu que 5.0 / 3 fonctionne...

Je ne vois pas pourquoi tu laisses des utilisateurs finaux non
programmeurs faire des choses sans les verifier. Faudrait donner un
peu plus de contexte pour qu'on puisse te proposer des solutions.


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

Il faudrait peut-etre surcharger personnellement le / et lui dire (au
compilateur) de n'appeler que le mien et pas les siens, comment faire cela ?

PurL


Avatar
Jean-Marc Bourguet
"PurL" writes:

Drole de vision des choses: le type du resultat d'un calcul depend des
arguments.


Je crois pas nan...

Ex :

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


Les arguments de / sont des entiers donc le resultat est entier.


Non, les arguments de / ne sont pas QUE des int,


Desole, 5 et 3 sont des entiers.

y'a des surchages !


Il y a des surcharges sur /, pas sur les literaux. La surcharge de /
choisie depend des types des arguments, ici deux entiers.

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 ne vois pas pourquoi tu laisses des utilisateurs finaux non
programmeurs faire des choses sans les verifier. Faudrait donner
un peu plus de contexte pour qu'on puisse te proposer des
solutions.


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


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

Il faudrait peut-etre surcharger personnellement le / et lui dire
(au compilateur) de n'appeler que le mien et pas les siens, comment
faire cela ?


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

A+
--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org



Avatar
Falk Tannhäuser
PurL wrote:
Je sais que par défaut, quand le compilateur (à l'exécution) à besoin de
variables intermédiaires pour effectuer une ligne de calcul, celles-c i sont
de type int. Ce qui parfois (meme tres souvent quand il s'agit de divis ions)
introduit de mauvais résultats. Comment faire pour forcer le compilat eur
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


Facile:

#include <string>
#include <fstream>
#include <iostream>
#include <cstdlib>
#include <cassert>
#include <cstdio>

double call_awk(std::string const& expr)
{
static char const tmpfilename[] = "/tmp/callawk.tmp";
std::string cmd_line = std::string("awk 'BEGIN {print ") + expr + "}' > " + tmpfilename;
int system_rslt = std::system(cmd_line.c_str());
assert(system_rslt == 0);
std::ifstream in(tmpfilename);
assert(tmpfilename);
double result; in >> result;
assert(in || in.eof());
std::remove(tmpfilename);
return result;
}

#define PURL_EXPRESSION(expr) call_awk(#expr)

int main()
{
double d = PURL_EXPRESSION( 5 / 3 );
std::cout << d << 'n';
return 0;
}

SNCR, Falk

Avatar
PurL
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.
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.

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.
Comment forcer l'apel avec les arguments de type double meme si le
compilateur veut utilisé celui avec les int ?

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


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.

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

A+


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

PurL


Avatar
Serge Paccalin
Le mardi 1er février 2005 à 12:00, PurL a écrit dans fr.comp.lang.c++ :

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.


Tu confonds « résultat correct » avec « résultat que *JE* veux ». Ce
sont deux choses différentes. 5 / 3 -> 1 *EST* un résultat correct,
puisque c'est celui que demande la norme.

--
___________ 2005-02-01 12:16:21
_/ _ _`_`_`_) Serge PACCALIN -- sp ad mailclub.net
_L_) Il faut donc que les hommes commencent
-'(__) par n'être pas fanatiques pour mériter
_/___(_) la tolérance. -- Voltaire, 1763

Avatar
Matthieu Moy
"PurL" writes:

Mais dans "float a = 5;", a est un float et est egal à 5,


Pas vraiment.

donc 5 est bien codé sous le format d'un float et non d'un int.


Pas du tout. 5 est un littéral, entier, c'est le "=" qui fait la
conversion.

Pas d'autres solutions ?


A mon avis, le vrai problème est que tu veuilles écrire "5 / 3" dans
tes programmes. Un programme bien écrit ne doit pas utiliser de
constantes litterales au milieu du code. Tu aurais écrit

const float constante1 = 5; // trouver un meilleur nommage !
const float constante2 = 3;

...

float a = constante1 / constante2;

Tu ne te serais même pas posé la question ...

--
Matthieu

Avatar
Jean-Marc Bourguet
"PurL" writes:

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.
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.


5 est un int qui est converti en float.

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.


Tout depend de ce que tu appelles resultat correct. Comme je l'ai
ecrit, les regles de resolution de surcharge ne prennent pas en compte
le contexte dans lequel apparait une expression. Et je ne veux pas
essayer de voir ce que ca donnerait la surcharge sur le resultat avec
les conversions implicites.

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


Tu connais la reponse, tu l'as donnee.

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


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.


Soit tu definis ton langage que tu compiles (vers du C++ si tu veux)
ou tu interpretes (auquel cas reutiliser qqch comme TCL/Python/... est
aussi une option), soit tu vis avec.

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org



Avatar
Pierre Maurette
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 ?
- Choisir un autre langage que C++ non traité pour un langage macro

ciblant des utilsateurs lambda qui ne connaissent pas C++ (le C
suffirait également).
- Analyser le texte de la macro, et en profiter pour signaler les
erreurs avant de compiler la DLL.

Le problème précis de float a = 5/3; : à mon avis ce n'est pas les
transtypages de C++ qui sont critiquables, mais l'opérateur /, ou plutôt
l'absence d'opérateur de division euclidienne. Mais comme pour beaucoup
de points de détail de C et de C++, c'est comme ça, c'est paraît-il ce
qui en fait le charme.
Notez que ce problème est également le votre. Donc pourquoi ne pas
l'aborder dans la documentation de votre appli, signalant que les
résutats de / peuvent paraître étranges, expliquant la différence entre
divisions réelle et euclidienne, et proposant l'utilisation de IDIV et FDIV:

inline float FDIV(float a, float b)
{
return a / b;
}

inline int IDIV(int a, int b)
{
return a / b;
}

FDIV(5, 3) donne bien 1.6667. Une seule fonction surchargée ne
conviendrais pas. D'une part, lambda ne sait pas caster pour résoudre
les ambiguïtés, d'unautre coté, ça vous oblige à faire des paris sur les
souhaits de lambda. Pour lui, float f = 3; int i = 3; et la constante 3,
c'est pareil. C'est pour cette même raison que l'idée d'une classe (un
type numérique) est sans doute illusoire.
--
Pierre

Avatar
Alain Naigeon
"Jean-Marc Bourguet" a écrit dans le message news:

"PurL" writes:

Mais pour un utilisateur lambda, quand il rentre 5 / 3 et qui voit
un resultat de 1, il fait un bond sur sa chaise :))



AMHA c'est plutôt une question pour fr.ameublement ;-)
Parce que moi, quand je me demande combien de fois
je peux loger 3 dans 5, ben... j'arrive à une seule fois, donc
la valeur de ce qu'on appelle communément le quotient.

Et je vais pas
lui dire qu'il faut mettre 5.0 pour que ca marche :) (les
utilisateurs finaux ne sont pas informaticiens)



La réponse figurait dans ta question, pour éviter de leur
demander cette conversion, tu l'écris toi-même en aval
de ce qu'ils entrent. Et comme disait Jean-Marc, ça te
donne l'occasion de vérifier aussi qu'ils n'ont pas entré
le prénom de leur grand-mère (la norme ne garantissant
pas qu'une conversion en float donne son âge) :-)

--

Français *==> "Musique renaissance" <==* English
midi - facsimiles - ligatures - mensuration
http://anaigeon.free.fr | http://www.medieval.org/emfaq/anaigeon/
Alain Naigeon - - Strasbourg, France


1 2