OVH Cloud OVH Cloud

[Calcul] Problème étrange

69 réponses
Avatar
Rincevent
Bonjour à tous,
g un gros problème dans mon programme C++.
Voilà g 3 entier a,b et c
Je souhaite calculer la partie entière de (a/b)*c
J'utilise pour cela la fonction floor() de <cmath>
Or deux problèmes se présentent :

1) Le compilateur renvoie 0 lorsque je lui demande de calculer (a/b)*c (et
ce, alors que les valeurs de a,b,c ne devraient pas donner un tel résultat)

2) Le compilateur m'insulte lorsque j'essaie d'appliquer la fonction floor()
à (a/b)*c (motif : l'argument n'est pas un double...)


- Je suppose qu'il doit exister une fonction pour convertir des rapports
d'entier en double, non ?
- Et inversement pour passer d'un double codant un entier --> en type int ?
- floor() attend un double comme argument... Soit mais quel est le type duy
résultat ? un double ? un int ?
- comment résoudre cet épineux problème de façon élégante ??? ;-)

Quelqu'un peut-t-il m'aider ?
Merci d'avance !

Rincevent

10 réponses

3 4 5 6 7
Avatar
Gabriel Dos Reis
--=-=- Content-Type: text/plain; charset=iso-8859-15
Content-Transfer-Encoding: 8bit

"Alain Naigeon" writes:

[...]

| Ce n'est certainement pas une raison, à mes yeux, pour
| violer grossièrement le bon sens en permettant que le
| type d'un nombre d'habitants puisse être négatif.

Quel est le type de 180000, en C ou C++ ?

| L'idée
| de bricoler des gardes-fous par des tests à l'exécution
| n'est qu'un pis aller, vraiment pas séduisante quand il
| existe un type qui colle avec le domaine de définition
| de ce qu'on veut représenter.
| Un nombre d'habitants est, par nature, non signé. Je

--=-=- Content-Type: text/plain; charset=iso-8859-1
Content-Transfer-Encoding: 8bit


Ce n'est pas à un physicien que je vais dire cela, mais je crois tu
confonds implicitement un nombre avec unité avec simplemennt un
nombre. Il n'y a pas de nombre avec unité en C ou C++. Tu peux
introduire une classe en C++, si tu veux.

--=-=- Content-Type: text/plain; charset=iso-8859-15
Content-Transfer-Encoding: 8bit


| choisis donc le type "unsigned int", qui signifie, si je
| ne m'abuse : "non signé". Donc, si quelque chose
| cloche par après, c'est la faute du langage, pas la
| mienne !

--=-=- Content-Type: text/plain; charset=iso-8859-1
Content-Transfer-Encoding: 8bit


Non, c'est le tien : la syntaxe des types n'est pass tout.
Avec ton raisonnement, un débutnt qui pense qu'il a un calcul complexe
à faire sur le nombre d'habitant d'une ville devrait utiliser
complex<unsigned>.

--=-=- Content-Type: text/plain; charset=iso-8859-15
Content-Transfer-Encoding: 8bit


| (en plus, ce n'est pas en me disant que ça vient du C
| qu'on va me convaincre, mais alors là pas du tout ;

--=-=- Content-Type: text/plain; charset=iso-8859-1
Content-Transfer-Encoding: 8bit


que tu le veilles ou non, la compatibilité avec le C est un facteur
majeur. Stroustrup savait comment inventer un très beau langage
incompatible avec C. Beaucoup de gens ont fait/font ça, ils écrivent des
papiers académiques, puis ils en inventent d'autres, puis ils
vont faire autre chose.

[...]

--=-=- Content-Type: text/plain; charset=iso-8859-15
Content-Transfer-Encoding: 8bit


| focntions, et par nostalgie je vais même l'appeler
| "this", pourquoi pas, hein ? :-) )

--=-=- Content-Type: text/plain; charset=iso-8859-1
Content-Transfer-Encoding: 8bit


Et tu ne serais pas le premier. J'en connais plein qui vont ça tous
les jours :-)

-- Gaby

--=-=-=--
Avatar
Gabriel Dos Reis
"Alain Naigeon" writes:

| je ne suis réaliste, travaillons avec ce qu'offre le langage. Ce que je dis
| simplement, c'est que s'il existe un type, alors c'est vraiment bizare
| de s'en passer.

Ce serait vraiment bizarre de se servir d'un type juste parce qu'il
existe non parce que sa sémantique convient.

-- Gaby
Avatar
Vincent Guichard
Demandez à quelqu'un qui fait du VB s'il fait attention
d'utiliser la division entière quand il en a besoin (au moins
en Pascal, il me semble qu'il fallait convertir explicitement
le résultat de la division pour le ravoir en entier).
Je fais pas mal de VB, (pas forcement par choix personnel, mais c'est

comme ça ;) ) et je fais attention attention d'utiliser la division
entière () qu'en j'en ai besoin, et la division "classique" (/) quand
j'en ai besoin.

Vincent Guichard

Avatar
Samuel Krempp
le Wednesday 26 May 2004 06:32, écrivit :

En quoi int est-il préférable ? On a aussi les phénomènes de cyclicité,
mais en plus, ils ne sont pas spécifiés par la norme.


ben les int distinguent nbres positifs et nbres négatifs, et l'effet
cyclique n'intervient que pour des grandes valeurs.
(alors que n-p, pour des valeurs unsigned même faibles, nous impose la
cyclicité)

AMA l'utilisation du sous-ensemble des nombres positifis dans int est plus
naturelle à l'esprit que celle d'unsigned.
enfin, avec bcp d'habiute en calculs unsigned, j'imagine qu'on assimile les
pièges de l'arithmétique unsigned.

ensuite, mais c'est personnel, je trouve avantageux de laisser un peu de
redondance aux données pour rendre plus probable la détection de problèmes
éventuels, et là unsigned pose un problème : on a pas de test pour esperer
avoir une chance de detecter des valeurs invalides (évenement probable du
fait justement de la mixité signed/unsigned à prévoir et des conversions
mal-à-propos)


--
Sam

Avatar
Pierre Maurette
"Alain Naigeon" typa:
Le problème, c'est ce qu'on entend par « division ». Si tu démandes à un
non-informaticien quelle est la valeur de 1/3, il va te dire un
tiers. Et non 0.
S'il s'agit d'un partage entre frères et s'il sait vivre, il dira "à


peu près 33 cl" pour un kil de rouge, et "Grands Dieux, zéro" s'il
s'agit de la maman. Le non-informaticien et non-mathématicien fait
très bien la différence entre division entière et division réelle.
;-) bien sûr.

C'est peut-être un problème d'éducation pour nous tous. On n'insiste
pas assez, au départ, sur le fait qu'un opérateur fonctionne autrement
avec chaque type. C'est ainsi que la rencontre d'une multiplication
non commutative nous a tous plongés, un jour, stupéfiés.
Donc, comme c'est un phénomène général, je ne suis pas sûr que
la solution soit de modifier le symbole opératoire, vu qu'on verra
assez vite qu'il n'en faut pas deux, mais trois, quatre, etc.
Donc gardons le signe, en sachant qu'il agit sur des êtres différents.
Parce, ton idée, elle conduit à distinguer aussi sqrt(int) de sqrt(float),
etc. Donc, il faudait les appeler différemment aussi ?
Et dans un langage qui implémenterait les matrices et leurs
opérations comme type de base, il faudrait aussi un autre symbole
pour leur multiplication ? Ca commence à faire beaucoup.
Je ne crois pas que l'on puisse généraliser. Le cas de la division est

particulier, les deux symboles désignent des opérations différentes
imaginables sur les mêmes données. En Delphi, les opérations :
Extended := Integer div Integer;
Extended := Integer / Integer;
ne donnent pas généralement le même résutat.
--
Pierre


Avatar
Michel Michaud
"Vincent Guichard" a écrit dans le message
de news:c92ccl$1vb$
Demandez à quelqu'un qui fait du VB s'il fait attention
d'utiliser la division entière quand il en a besoin (au moins
en Pascal, il me semble qu'il fallait convertir explicitement
le résultat de la division pour le ravoir en entier).
Je fais pas mal de VB, (pas forcement par choix personnel, mais

c'est comme ça ;) ) et je fais attention attention d'utiliser la
division entière () qu'en j'en ai besoin, et la division
"classique" (/) quand j'en ai besoin.


Je crois que je n'ai pas dit les choses correctement. En disant
« quand il en a besoin » je voulais dire « quand c'est tout
ce dont il a besoin ». Si tu as absolument besoin de la division
entière, je suis sûr que tu la mettras puisque sinon ton programme
ne fonctionnera pas. Mais si la division entière est suffisante
(est tout ce dont tu as besoin), alors que / (division réelle)
fonctionne aussi, tu vas vraiment penser à mettre ?

--
Michel Michaud
http://www.gdzid.com
FAQ de fr.comp.lang.c++ :
http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ/


Avatar
Loïc Joly
wrote:
Pour les classes on conseille de s'inspirer de "l'univers du problème"
; serait-ce une tare de faire de même pour d'autres types, encore plus
basiques ? Quand une variable représente un entier qui n'a aucun sens
autre que positif, cela me révulse absolument qu'il ne soit pas
unsigned.



Tu veux dire que ça te révulse qu'il puisse représenter les valeurs en
dehors du domaine. Moi aussi. Par exemple, si je veux un type qui
représente un dé, je ne veux pas non plus qu'il puisse représenter un 0,
ou un 100.


Si tu faisais des jeux de rôle, un dé valant 0 ou 100 ne te ferait pas
peur... ;)

Malheureusement, C/C++ n'a pas des types à sous-étendu (subrange
types). On peut les implémenter au moyens des classes, mais le résultat
est assez lourd. Alors, en général, on s'en passe. (Peut-être à tort, je
ne sais pas. Un template Subrange< typename T, T, T > ne doit pas poser
de grands problèmes.)


Je pense que ce n'est pas trivial quand même. En particulier :
Subrange<int, 0, 10> a, b;

Quel doit être le type de a-b ? Subrange<int, 0, 10>, ou bien
Subrange<int, -10, 10> ?

Et même mathématiquement, quelle est l'élément neutre de l'addition
définie sur Subrange<int, 1, 2> ?

--
Loïc


Avatar
Jean-Marc Bourguet
Loïc Joly writes:

Je pense que ce n'est pas trivial quand même. En particulier :
Subrange<int, 0, 10> a, b;

Quel doit être le type de a-b ?


int naturellement. Comme en Ada je vois cela comme une contrainte.
Autrement dit c'est assez facile a ecrire: outre ce qui en fait un
type de valeur (copie, assignation) il faut simplement une conversion
implicite vers int, un constructeur prenant un int faisant la
verification d'intervalle et un operateur d'assignation prenant un int
(et verifiant egalement la contrainte). Les deux points qui meritent
plus ample reflexion me semble est-ce que le constructeur prenant un
int est explicite ou pas et est-ce qu'on fournit bien l'operateur
d'assignation prenant un int.

Je ne vois pas pourquoi on ferait quelque chose qui se comporte comme
un vrai nouveau type. Je vois l'utilite d'introduire de vrais
nouveaux types a partir des types de bases -- j'ai meme commence a
ecrire une proposition dans ce sens mais je n'ai pas le temps
necessaire et chaque fois que j'y reflechis je trouve des nouveaux
problemes au point que je commence a douter de la possibilite
d'introduire ca plus ou moins proprement en C++ -- mais je crois que
pour cette appplication, le sous-type contraint (pour parler avec la
terminologie Ada) est plus utile.

Et même mathématiquement, quelle est l'élément neutre de l'addition
définie sur Subrange<int, 1, 2> ?


Pourquoi faudrait-il obligatoirement un neutre? Mais de toute maniere
dans la meme optique que ci-dessus le neutre est 0.

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
Vincent Guichard
"Vincent Guichard" a écrit dans le message
de news:c92ccl$1vb$


Demandez à quelqu'un qui fait du VB s'il fait attention
d'utiliser la division entière quand il en a besoin (au moins
en Pascal, il me semble qu'il fallait convertir explicitement
le résultat de la division pour le ravoir en entier).


Je fais pas mal de VB, (pas forcement par choix personnel, mais
c'est comme ça ;) ) et je fais attention attention d'utiliser la
division entière () qu'en j'en ai besoin, et la division
"classique" (/) quand j'en ai besoin.



Je crois que je n'ai pas dit les choses correctement. En disant
« quand il en a besoin » je voulais dire « quand c'est tout
ce dont il a besoin ». Si tu as absolument besoin de la division
entière, je suis sûr que tu la mettras puisque sinon ton programme
ne fonctionnera pas. Mais si la division entière est suffisante
(est tout ce dont tu as besoin), alors que / (division réelle)
fonctionne aussi, tu vas vraiment penser à mettre ?



Comme ça, là, je ne vois pas de cas (hors les cas triviaux ou on fait la
division de deux entiers dont le dividende est un multiple du diviseur)
ou la division entière et la division réelle ont des résultats
équivalents. Mais si je tombe sur un tel cas, je pense qu'en effet
risque d'utiliser la division réelle et non pas la division entière.

Vincent Guichard



Avatar
kanze
drkm wrote in message
news:...
writes:

Pierre Maurette wrote in message
news:...

Je vous laisse, par rapport à ce que vous souhaitez, juger de
l'oportunité d'un ajustement par floor(). Personnellement, je ne
l'utiliserais pas, puisque c'est une fonction double.


Si les valeurs sont signées, il a intérêt à passer en flottant de
toute façon. La division avec des résultats négatifs n'est pas bien
définie en C++.


Pourrais-tu être un peu plus précis sur ce qui n'est pas bien
défini, stp ? Je n'arrive pas à voir ce dont tu parles.


Quand je dis « pas bien défini », je parle en langage courant, et non
langage de la norme. Au sens de la norme, une division entière dont le
résultat doit être négatif n'a pas un comportement indéfini, mais le
résultat est spécifié par l'implémentation.

C99 l'a spécifié. (Ce n'était pas spécifié dans les versions antérieur
de C non plus.) Dans la pratique, j'imagine que la prochaine version de
la norme C++ suivra C ici, et le spécifiera. Dans la pratique, aussi, si
C a crû pouvoir le spécifier, c'est que toutes les implémentations
aujourd'hui donnent bien le même resultat. (La question est simple :
est-ce que -1/3 vaut 0 ou -1 ? C99 exige 0, et c'est ce que donne toutes
les implémentations de C++ actuelles. Mais la norme C++ permet les
deux.)

--
James Kanze GABI Software
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



3 4 5 6 7