0

I am writing a program and I noticed that my a variable is not calculated correctly. Here is the code:

int a = int(34 / 40 * 40);
std::cout << a << std::endl;

When I run it, it outputs 0. However, 34 / 40 * 40 is 34.

I suppose the issue is in division, because if I replace it with multiplication (34 / 40 = 0.85), it works just fine:

int a = int(0.85 * 40);
std::cout << a << std::endl;

Output: 34 In my case I can just use multiplying, but what if somebody will need to divide variables?

  • 3
    when you divide integers the result is an integer. You want `int a = 34.0 / 40.0 * 40.0;` – 463035818_is_not_an_ai Feb 24 '23 at 10:40
  • 2
    `34 / 40 * 40` is only 34 in mathematics not in C++ (or many other programming languages). In C++ `34 / 40` is zero, the result of dividing two integers is always another integer. – john Feb 24 '23 at 10:45

4 Answers4

2

If you divide an integer by an integer, you will always get an integer as a result. Therefore, when an integer is divided by an integer, the reminder of the result is discarded, in your case .85 is discarded.

int = int / int

However, if one of the numerator or denominator is a floats your result will also be a float.

float = float / float
float = int / float
float = float / int

In your case:

float numerator = 34;
float denominator = 40;

int a = numerator / denominator * 40;

Pay attention that multiplication groups from left to right like pointed out by Pete Becker

Leo
  • 48
  • 5
  • I'd remove the `int( ..)` cast, because its a code smell that is not needed here. Assigning the result to `a` is sufficient to get an `int` – 463035818_is_not_an_ai Feb 24 '23 at 10:53
  • 2
    Minor point: if **either** the numerator **or** the denominator is a float (and the other is an int or a float) the result is a float. – Pete Becker Feb 24 '23 at 13:52
  • 2
    This is missing an important point: division and multiplication group left to right. That is, `numerator / denominator * 40` means `(numerator / denominator) * 40` and not `numerator / (denominator * 40)`. – Pete Becker Feb 24 '23 at 13:54
  • @PeteBecker good calls, i have edited the answer according to your feedback. – Leo Feb 24 '23 at 14:14
0

Your problem is that integer arithmetic is performed with integers all the way through, at no point will any operand be changed to a floating point format unless you specifically ask for it.

As such 34 / 40 == 0 because all decimals are stripped, and then trivially 0 * 40 == 0.

On the other hand 0.85 * 40 features operands of types double and int, and as such floating point arithmetic is used and the result is 34.0 (type double), which is then converted to the int 34.

Note that a single floating point variable will cause the result to be floating point, so 34.0 / 40 * 40 will also work. BUT beware that this only applies from the point the floating point is introduced in the expression grouping (which then turns into a discussion of operator precedence, see (*) at the bottom).

So (2 / 3) + (4.0 / 5) == 0.8 because (2 / 3) == 0 is evaluated using integer arithmetic, then (4.0 / 5) == 0.8 because one of the operands is floating point, and finally 0 + 0.8 == 0.8.

If you are in doubt, then apply parenthesis to force the grouping you want. On that note 34 * (40 / 40) also work - in both integer and floating point.

(*) How expressions are evaluated depends on operator precedence and manual parenthesis grouping. So for example 34 / 40 * 40 groups as (34 / 40) * 40 because multiplication and division are left-to-right associative and of equal precedence.

On the other hand 2 / 3 + 4.0 / 5 groups as (2 / 3) + (4.0 / 5) because multiplication and division have higher precedence than addition. This also means that 2 / 3 + 4.0 / 5 and 4.0 / 5 + 2 / 3 both evaluate to the same result, since in both cases the 2/3 group is evaluated using integer arithmetic before the two groups are added.

Frodyne
  • 3,547
  • 6
  • 16
  • "onward" isn't really a good description of how things group: `34 / 40.0 * 40` will also work. And it's not about evaluation order; it's about **grouping**. Division and multiplication group left to right, so `a / b * c` is `(a / b) * c`. Evaluation order is about what happens when: `f() / g() * h()` groups left to right, just like the previous expression, but the order of evaluation of the three function calls is unspecified. – Pete Becker Feb 24 '23 at 13:58
  • @PeteBecker I used evaluation order in the mathematical sense, but I can see how that could be misunderstood given that *order of evaluation* has a different meaning in programming, so I replaced it with *grouping* per your suggestion. I have also replaced "onward" with a note that should explain when integer to floating point promotion happens in a more comprehensive way. – Frodyne Feb 24 '23 at 14:44
0
>> 0    int a = int(34 / 40 * 40);
>> 1    int a = int((34 / 40) * 40);
>> 2    int a = int(0 * 40);
>> 3    int a = int(0);
>> 4    int a = 0;

Please try this

int a = int(34.0 / 40 * 40);
-2
#include <iostream>

int main() {
    float a = 34.0 / 40.0;
    int b = a * 40;
    std::cout << a << std::endl;
    std::cout << b;
    return 0;
}

Try this, because at division the C++ compiler make cast to integer, type used on variable. On example above the division is do with float variable.

Community
  • 1
  • 1
Jean Dias
  • 1
  • 1
  • 4