c ++ Problem when dividing 2/3

3

I need to multiply an X value by 2/3 (Two Thirds), for which I am using the following:

#include<iostream>

using namespace std;

int main() {
    double var;

    var=2/3;
    cout<<var<<endl;
    return 0;
}

and to my surprise I got 0 as an exit. I thought it was due to the number of decimals so I tried the following

#include<iostream>
#include <iomanip>

using namespace std;

int main() {
    double var;
    cout.setf( ios::fixed );
    cout<<setprecision( 2 );

    var=2/3;
    cout<<var<<endl;
    return 0;
}

But in the same way I get output of 0.00 I am using Code :: Blocks 16.01, but I also tried it in Dev-C ++ 5.11 and got the same output

    
asked by José F 26.10.2017 в 03:32
source

3 answers

5

It's a very funny problem , I summarize it with an analogy:

  • You have a cookie.
  • You have a shoe box.
  • You put the cookie in the shoe box.

How many shoes are in the shoe box ?. Zero.

The above analogy does not quite fit this situation but it serves to illustrate that you are working with two different things: integers ( int ) and double precision floating point numbers ( double ).

Literals .

In C ++ 1 a set of information that is interpreted by the compiler "as written" is a literal. In C ++ 1 there are several types of literals:

  • Numeric (integer and floating point).
  • Character.
  • String.
  • Boolean.
  • Null pointer 2 .
  • Defined by the user 2 .

Numeric literals.

Literals have an underlying type, which varies according to the prefix or suffix:

| Sufijo | Ejemplo |        Tipo        |
+--------+---------+--------------------+
|        | 1       | int                |
| u      | 2u      | unsigned int       |
| l      | 3u      | long               |
| ll     | 4ll     | long long          |
| ull    | 5ull    | unsigned long long |

If the literal contains a period, it will be interpreted as a floating point number:

| Sufijo | Ejemplo |        Tipo        |
+--------+---------+--------------------+
|        | 1.      | double             |
| f      | .2f     | float              |
| l      | 3.l     | long double        |

It is not relevant to this question, but the suffixes can be capitalized or lowercase and the literal can be written in hexadecimal, octal or binary.

Mathematical operations and type promotion.

C ++ 1 does not perform operations with different types, before operating transforms the operands to a common type following the rules of C ++ standard in section §5.9.10 (the translation and highlighted by me):

  

Several binary operators that expect operators of arithmetic or enumerated type cause conversions and return types in a similar way. The purpose is to return a common type, which is also the result type . This pattern is called usual arithmetic conversions , which is defined as follows:

     
  • ...
  •   
  • 10.2 If any of the operands is of long double , the other must be converted to long double .
  •   
  • 10.3 Otherwise, if any of the operands is double , the other must be converted to double .
  •   
  • 10.4 Otherwise, if one of the operands is float , the other must be converted to float .
  •   
  • 10.5 Otherwise, the integral promotions must be applied to both operands. Then the following rules will be applied to the promoted operands:      
    • 10.5.1 If both operands have the same type, no additional conversion is required .
    •   
    • 10.5.2 Otherwise, if both operands have signed types or both types have unsigned types, the operand with the lowest rank type will be converted to the type with the highest rank.
    •   
    • 10.5.3 Otherwise, if the operand that has unsigned integer type has a range greater than or equal to the range of the type of the other operand, the operand with signed integer type must be converted to the operand type with integer type without sign.
    •   
    • 10.5.4 Otherwise, if the type of the operand with signed integer type can represent all the values of the type of the entire inoperative operand, the pounder with unsigned integer type must be converted to the type with the operand with type whole with a sign.
    •   
    • 10.5.5 Otherwise, both operands must be converted to an unsigned integer type corresponding to the type of the entire operand without a sign.
    •   
  •   

In your mathematical operation of 2/3 we see that you use two numeric literals, both literals are of type int (they lack suffix) so the result of the operation will also be type int . The entire division of an X number by a number Y being Y > X is always 0 and that is the result that is stored in your variable var of type double .

Proposal.

If the operands of your operation are of type double the result will be double :

var=2./3.;

Even if one of the operands is double would be enough:

var=2/3.;

1 And other languages.

2 Exclusive to C ++.

    
answered by 26.10.2017 / 10:35
source
4

Your problem is very simple:

double var = 2 / 3;

That, from the compiler's point of view, is equivalent to

double var = (int)2 / (int)3;

Do you see it already? var is a double , but the literals you are using, the numbers , are integers .

The actions occur separately: first, the integer 2 is divided by the integer 3; the result is another integer, with value 0 . After , that integer 0 is assigned to your variable double .

Change your code to

double var = 2.0 / 3.0;

With that, you are using literal double , and the result is as expected.

  

0.666667

    
answered by 26.10.2017 в 06:04
0

As you have been told the whole part of 0.666667 (or 2/3) is 0. Decimals are discarded since you have defined the variable as integer. If you want decimals to be taken into account you will have to define it in such a way that it accepts decimals (double, float ...)

    
answered by 26.10.2017 в 11:31