-1

what is wrong with my code? its converting inches and feet and comparing them in meters. if i enter 12 for inches and 1 for feet it says that the numbers are not equal. Is this a known issue with g++? Can somebody explain this to me?

#include <iostream>
#include <cmath>
using namespace std;

int main()
{
    double in, ft, m1, m2;
    cin >> in >> ft;
    m1 = in * 0.0254;
    m2 = ft * 0.3048;
    cout << m1 << '\t' << m2 << '\n' << endl;
    // to show that both numbers are equal
    if (m1 == m2) cout << "yay";
    else cout << "boo";
}

Does anybody else have this issue?

NathanOliver
  • 171,901
  • 28
  • 288
  • 402
  • possible duplicate of [Most effective way for float and double comparison](http://stackoverflow.com/questions/17333/most-effective-way-for-float-and-double-comparison) – NathanOliver Jun 05 '15 at 16:56
  • What Every Computer Scientist Should Know About Floating-Point Arithmetic: http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html –  Jun 05 '15 at 16:58
  • how many digits did you print? – Glenn Teitelbaum Jun 05 '15 at 16:58
  • its not about comparing variables more effectively, its about the compiler not comparing numbers properly. if i enter 12 for inches and 1 for feet it should say that they are equal (m1 and m2 are both 0.3048 in meters) but it does not – Josh Carew Jun 05 '15 at 17:06
  • i am a beginner, so whatever answer is given is gonna have to be dummed down as much as possible – Josh Carew Jun 05 '15 at 17:07

3 Answers3

0

What you're seeing is a result of inexact floating point representation. Base 2^n floating point numbers cannot represent all base 10 decimal values exactly. Thus, when you do something simple like multiplying 12*0.0254 you get the very odd result of 0.3047999.......6, whereas if you compute 1*0.3048 you get the expected result of 0.3048. The problem is that 0.0254 isn't being stored exactly; instead, the closest approximate value (something like 0.0253999999....98) is used. The difference is small but can become noticeable when you use the inexact value in a calculation, and then compare it to another value which doesn't suffer from rounding issue such as 0.3048. A basic rule to keep in mind is that you should never compare floating point values for equality; instead, compare them in a manner that allows for an acceptable error, e.g. instead of comparing values in the following manner:

if(val1 == val2)...

use something like

if(abs(val1 - val2) < 0.0000001)...

so that the two variables will be considered equal if their values differ by less than 1/10,000,000 (which is pretty close :-).

rsd_unleashed
  • 151
  • 2
  • 12
  • With all due respect grab a pen and paper and Plz... explain how did u get 12*0.0254 = 0.3047999... ??? – Shivam Jun 05 '15 at 17:07
  • yeah i agree with shivam, you can't get more decimal places. – Josh Carew Jun 05 '15 at 17:11
  • @Shivam - it's not about pen and paper. If you calculate 12 * 0.0254 *exactly* using a pen and paper method, you will get the correct answer. However, floating point arithmetic performed by a computer is not exact, in part due to the fact that only a limited subset of real numbers can be represented, and also by the fact that all calculations are also truncated to the limited precision of the variable. Which makes floating point arithmetic done by a computer very much inexact, even when you know very well what you're doing. – twalberg Jun 05 '15 at 17:26
  • then why when i print, line 11, both m1 and m2 variables, they are the same at 0.3048? – Josh Carew Jun 05 '15 at 17:28
  • @twalberg thanks for the explanation, i am glad i asked my doubt :) – Shivam Jun 05 '15 at 17:38
0

The reason that the numbers don't match is that computers use a binary representation of numbers which leads to inaccuracies when trying to represent decimal numbers.

You think the number is 0.3048 (because that's what you coded) - but when compiled, the computer can only represent this as the nearest equivalent in binary format (see IEEE floating point for more info). So the number might be something extremely close to 0.3048, but not precisely that.

After you've done your calculations, you compare the numbers - but if the two are not absolutely identical in their binary representations, they won't match.

One simple way to solve it (but by no means the only solution) it to subtract the two operands and check how close to zero it is. If:

fabs(a - b) < 0.00001

(an arbitrary amount), then you can presume the values are the same.

adelphus
  • 10,116
  • 5
  • 36
  • 46
  • so... can you not compare floating point numbers after manipulation? – Josh Carew Jun 05 '15 at 17:13
  • I ran into this issue when i was going through programming-principles and practice using c++. It was the drill on page 124. – Josh Carew Jun 05 '15 at 17:16
  • It would be nicer if you could provide with a solution to tackle situations like this... tx – Shivam Jun 05 '15 at 17:16
  • the numbers should be absolutely identical i printed them before they are compared – Josh Carew Jun 05 '15 at 17:24
  • Printing numbers in the way you have coded is rounding the actual value. Take a look at http://stackoverflow.com/questions/4217510/how-to-cout-the-correct-number-of-decimal-places-of-a-double-value to see how to show the "real" number being used. – adelphus Jun 05 '15 at 17:29
0

@Josh, add this to your code and run it

cout << m2-m1; 

u will be surprised, answer is not zero

For the problem in code, changing data type from double to float fixes the problem

float in, ft, m1, m2;
Shivam
  • 457
  • 1
  • 6
  • 15