Pendant que je programmais en C ++ il y a quelques jours, j'ai fait cette erreur (que j'ai l'habitude de faire!). Dans une partie de mon code, j'avais 1/6 et je m'attendais à ce que ce soit 0.16666666666 ce qui n'est pas le cas. Comme vous le savez tous, le résultat est 0 - C, C ++, Java, Python, tous se comportent de la même manière.
Je le poste sur ma page Facebook et maintenant il y a débat pour savoir s'il existe un langage de programmation qui 1/6
se comporte de la même manière que 1.0/6.0
.
>> 1 / 6
->== 0.166666666666667
1/6
est en fait 1/6 (type fractionnaire) qui, contraintDouble
, est de 1,66666 ...Réponses:
Tout le monde a oublié Pascal?
1/6
rendements0.1666666...
(quelle que soit la précision prise en charge).1 div 6
les rendements0
On peut se demander si la règle C est une erreur. Presque tous les opérateurs arithmétiques de C, où les opérandes sont du même type, donnent un résultat du même type. Il y a quelque chose à dire pour la cohérence.
De plus, puisque C est principalement destiné au code au niveau du système, la plupart des programmes C n'utilisent pas du tout de virgule flottante. À un moment donné, l'ajout accidentel de code à virgule flottante à un programme qui n'en aurait pas besoin autrement pourrait être un problème grave. C'est probablement toujours le cas, pour les petits systèmes embarqués - qui, encore une fois, sont une cible majeure pour C.
Dans la plupart des programmes C, tronquer la division entière est probablement exactement ce que vous voulez de toute façon.
Si a
1 / 6
donné un résultat à virgule flottante en C, alors:double
peut sembler le choix naturel, mais vous pouvez préférer la précision supplémentairelong double
)C aurait pu fournir des opérateurs distincts pour les deux types de division, mais le deuxième point ci-dessus s'appliquerait toujours: lequel des trois types à virgule flottante serait utilisé pour le résultat? Et comme il est assez facile d'obtenir une division en virgule flottante si vous en avez besoin (utilisez une constante à virgule flottante pour l'un des opérandes ou les deux, ou convertissez l'un des opérandes ou les deux en type à virgule flottante), cela n'a apparemment pas été '' t considéré que important.
Dans la version 1974 du manuel C (soit 4 ans avant la publication de la première édition de K&R), Ritchie ne mentionne même pas la confusion possible:
qui dit que si les deux opérandes sont de type
int
ouchar
, le résultat est de typeint
.Oui, c'est une source de confusion pour certains programmeurs C, en particulier les débutants - mais C n'est pas réputé pour être très convivial pour les novices.
la source
1.666666...
, ce qui est clairement faux. Mon excuse boiteuse est que le programme de test Pascal que j'ai écrit a été imprimé1.6666666666666667E-0001
En fait, ce comportement a été modifié dans Python 3 et il se comporte maintenant comme prévu (
//
est maintenant utilisé pour la division entière).la source
/
produit toujours une valeur à virgule flottante et un opérateur séparé (div
) est utilisé pour la division entière.Hors des langues dominantes, JavaScript. 1,0 / 6,0 = 1/6 = 0,16666666666666666.
Je ne vois pas cela comme surprenant. En règle générale, si une langue fait la distinction entre les types numériques entiers et à virgule flottante, la division de deux entiers produira un entier tronqué au lieu de flottant. Si ce n'est pas le cas, il s'agira très probablement par défaut d'opérations en virgule flottante. Cela devrait être le comportement attendu de la part du programmeur.
Gardez juste à l'esprit qu'il y a des choses supplémentaires qui pourraient également être en jeu ici, comme l'opérateur de division d'entier séparé déjà mentionné ou la conversion de type implicite.
la source
Il existe de nombreuses langues où les
((1/6)*6)
résultats en 1, pas en 0. Par exemple, PL / SQL, de nombreux dialectes BASIC, Lua.Par accident, dans tous ces langages, 1/6 se traduit par 0,166666667 ou 0,16666666666667 ou quelque chose de similaire. J'ai choisi la variante ((1/6) * 6) == 1 pour me débarrasser de ces petites différences.
la source
((1/6)*6)==1
variante pour me débarrasser de ces petites différences, mais il semble que j'ai surestimé les compétences en mathématiques de certaines personnes.Haskell considère que 1/6 et 1,0 / 6,0 sont identiques à 0,16666666666666666. Il rend également 1 / 6.0 et 1.0 / 6 comme étant également la même valeur.
Cela est dû au fait que les types numériques de base dans Haskell ne sont pas tout à fait les mêmes que dans d'autres langues. La vraie division entière est quelque peu ... compliquée.
la source
Oui, Perl le fait. Le one-liner
se traduit par la sortie de:
Je pense que PHP fonctionne de la même manière.
Modifié pour ajouter: Je pense également qu'une condition nécessaire (mais pas suffisante) pour
1/6 == 1.0/6.0
que la langue en question soit faiblement typée.la source
/
est surchargé automatiquement en fonction des types des arguments, mais cela semble être une violation du principe de moindre Étonnement à moi ...Dans Squeak Smalltalk
/
sur les entiers crée des objets Fraction. Donc, bien que ce ne soit pas la même chose que la division flottante,(1/6)*6
renvoie toujours 1.la source
Oui, je viens de vérifier ma TI-99 / 4A est construit en TI BASIC . Comme elle traite toutes les expressions numériques en virgule flottante, l'opération de division est également en virgule flottante.
la source
VB ( VB.Net , VB6 , VBA ...)
L'opérateur de division entier est \
la source
MATLAB. Les littéraux numériques sont doubles par défaut.
la source
Clojure utilise des fractions par défaut. Ce n'est pas la même chose que 1.0 / 6.0, mais vous pouvez le convertir avec
float
oudouble
quand vous en avez besoin.la source
Étonnamment, il semble fonctionner correctement dans Windows PowerShell (version 3) .
Semble également fonctionner en Python 3 comme l'a mentionné sepp2k. Les deux autres langues que j'ai facilement disponibles sur REPL, Scala et Ruby, font toutes deux une division entière et donnent 0.
la source
Le langage Rexx produit toujours une réponse arithmétiquement correcte. Par exemple: 5/2 = 2,5. Rexx est un excellent langage qui n'a pas été suffisamment utilisé. En théorie, quand un compilateur ne peut pas déterminer ce que vous voulez, il vaut mieux faire le bon calcul, cependant, cela peut ne pas être efficace. Rexx fournit également l'opérateur //.
la source