views:

227

answers:

5

I'm parsing a file and trying to decode coordinates to the right unit. What happens is that this code is evaluated to 0. If I type it into gdb the result is correct.

int pLat = (int)(
        (argv[6].data() == "plus" ? 1 : -1)
        * (     atoi(argv[7].data()) 
              + atoi(argv[8].data()) / 60. 
              + atoi(argv[9].data()) / 36000.)
        * 2.145767 * 0.0001);

I'm doing a (degrees, minutes, tenth seconds) conversion to wgs. Is there something wrong with this code?

+4  A: 

Just plugging in random values for argv[6..9] seems to produce numbers smaller than 1. When cast to int, these values will be truncated to 0. If your conversion factors are correct, you may need to use a floating-point type to represent the result.

warrenm
A: 

You are converting to int in the end which will cap all values to the smaller(!) int value. C does not round in this case.

[Edit: Sorry, my previous version of this answer contained a wrong part.]

Thorsten79
> whole calculation being done in integer format.This is not a problem. int is promoted to float whenever required - this is clearly defined by the language.
Suma
> In C there is a difference between 1 * 0.1 and 1.0 * 0.1.What difference? Both of this results in float, as integer is promoted to float by operator *.
Suma
+7  A: 

You are casting it to int, which means you are only taking the integral part.

(int)0.7 == 0. If the expression you cast to an int is < 1, the result will be 0 due to the cast. Since 2.145767 * 0.0001 is a very small number, the chances of this happening are pretty high.

Consider using floats or doubles exclusively.

In general:

(int)x.y == x for all floats and doubles x.y. (ignoring possible overflow)

IVlad
+4  A: 

I'll assume for now that you have defined

vector<string> argv;

and initialized it somehow.

string::data doesn't do what you seem to want. Actually, it does almost nothing. It just returns a const pointer to a version of the string, which isn't guaranteed to be null-terminated.

To compare a string to a character literal, just use ==.

To pass a string to a C function, use string::c_str.

And, you are putting a fractional number into an int.

double pLat = ( // use a floating-point type
        (argv[6] == "plus" ? 1 : -1) // compare string using ==
        * (     atoi(argv[7].c_str()) // get C string using c_str
              + atoi(argv[8].c_str()) / 60. 
              + atoi(argv[9].c_str()) / 36000.)
        * 2.145767 * 0.0001);
Potatoswatter
+7  A: 

Assuming you're trying to convert degrees to WGS84 coordinates, there are two errors:

  • The conversion factor is out by a factor of 10 (180/223 is approximately 2.145767*10-5, and you have 2.145767*10-4)
  • You are multiplying by the conversion factor when you should be dividing by it. This will give you a very small number, and the cast to int will give zero.
Mike Seymour
And it looks like the conversion from seconds to decimal degrees is also off by a factor of 10, 36000 instead of 3600.
Mark B
36000 is right, I get degrees, minutes and tenth seconds.But the rest was wrong, works now thanks
Alexander Stolz
Code that uses `atoi` cannot and will not work in general case. Any resemblance of "working" is temporary and purely accidental.
AndreyT