7
votes

C ++. La division 1 par n'importe quel nombre donne 0

Lorsque j'essaie de diviser 1/60 ou 1 / (60 * 60), il donne 0. Même dans la fenêtre de débogueur. Je suis un peu confus ce qu'il pourrait être, car 2/3 ou 2,5 / 6 donner des résultats.

My Code: P>

int main()
{   
    double k1 = 1/60;
    cout << k1
        << endl;
    double k2 = 1/(60*60);
    cout << k2
        << endl;

    return 0;
}


3 commentaires

Dites bonjour à la troncature entière.


@Victorhugo, le titre de titre le donna. Bien sûr que cela signifie que c'est un très bon titre.


" parce que 2/3 ou 2,5 / 6 donne des résultats " - Montrez-moi comment 2/3 donne un résultat autre que 0 .


3 Réponses :


2
votes

Le dénominateur doit être un nombre décimal aussi.

double k2 = 1/(double)myDenom;


2 commentaires

Au moins un numérateur ou un dénominateur doit être un type de point flottant. Il n'est pas nécessaire que ce soit le dénominateur: 1.0 / 60 fonctionne bien, aussi.


Oh, je pourrais jurer qu'il devait être le dénominateur. C'est ce que je me souviens de quelques années d'âge des années.



2
votes

La ligne double k1 = 1/60 sera évaluée par le compilateur en tant que constante de compilation. Comme il n'y a pas de "0.0" à la fin du nombre, 1/60 sera évalué via une division entière, et donc 0.


0 commentaires

11
votes

Étant donné que vos deux opérandes sont des entiers, le compilateur effectue une division entière (qui ne calculait pas la partie décimale). Si au moins un des opérandes est un type de point flottant (comme dans vos autres exemples), l'autre est promu et une division ponctuelle flottante est effectuée.

le correctif

Faites au moins un des opérandes d'un type de point flottant ( double ou float ); Vous pouvez faire cela par E.g.:

  • en faisant un double littéral 2 ( 60 est entier, 60.0 ou même 60. est double , 60.f est float )
  • à l'aide d'une distribution ( double (60) , (double) 60 ).

    personnellement, je préfère utiliser directement double littéraux - et non que la distribution a une pénalité de performance sur les compilateurs décents à mi-chemin, mais il se sent "faux" et verbeux en ce qui concerne simplement un littéral du type correct . (Évidemment, lorsque les deux opérandes sont des variables et non des littéraux, vous avez utiliser le casting)

    objections communes

    • "mais je l'affiche à un double !"

      De nombreux débutants sont confondus par ce fait, car ils pensent que l'attribution de 1 le résultat à un double doit être une sorte de pointe du compilateur. En fait, ce n'est pas.

      Les calculs / promotions effectués dans l'expression sont complètement indépendants du type de destination, ce qui n'est que la dernière étape. Les subexpressions sont évaluées pour ce qu'elles sont, sans tenir compte de la manière dont le résultat sera utilisé, de sorte que tous les promotions / opérations de type ne dépendent que du type des opérandes.

    • pourquoi voudrait-on une division entière?

      Plusieurs langues effectuent automatiquement la division de points flottante, même lorsque les arguments sont à la fois des entiers (par exemple VB6, IIRC), car il se sent plus intuitif pour les novices. Ce n'est pas comme ça dans C / C ++: la division fait partie intégrante lorsque les arguments sont entier, car dans de nombreux cas, vous ne vous souciez pas des décimales et / ou de préférer les raisons de performance de ne pas utiliser le FPU (la philosophie de fond en C et C ++ est "Vous ne payez pas pour ce que vous n'utilisez pas").

      Évidemment, le problème aurait pu être adressé à l'aide d'un opérateur distinct pour la division intégrale (VB, utilise à nouveau \ ), mais IMHO nous avons suffisamment d'opérateurs en C ++. :)

      1. Nitpickers 'Corner: Oui, ici, c'est une initialisation, pas une mission, mais nous parlons du même type d'idée fausse.
      2. Un "littéral" est une valeur incluse dans le code source.

0 commentaires