Division without using float. Possible?

Hi everyone,

I'm reading the NMEA coordinates off of a GPS unit. The lat/long as well as other info, gets stored into its own string (not String).

As part of the project I'm working on, I want those coordinates to be converted to google coordinates. The reason being is that an SMS will be sent, containing a ready-formed link with the position of a vehicle. To convert the NMEA to google coordinate system the minute.seconds info form the NMEA sentence will need to be divided by 60 eg: N3756.6050 = 37 + (56.6050 / 60) = 37.943416

I was wondering if that division could be made without using floats. After all I'm not interested on the arithmetic value of the number, only its text representation...

Why not using float? Other than the delay of floating point calculations, I'm trying to save as much as possible SRAM space, as I have a feeling that its size will be a show-stopper.

Thank you all in advance,
Nikos

Yes, you can use fixed point arithmetic.
But you should scale it up first by 10 to preserve 6 digit precision.

566050 * 10 /6 = 943416

After all I'm not interested on the arithmetic value of the number, only its text representation...

You don't give a rats ass what the result of the division is? Just so long as you can get a text representation of some incorrect calculation? Why not just call random() then?

I'd suggest going directly from the NMEA text format to the google text format. The difference is in the fractional minutes instead of angular minutes, you can look it up.

Dividing by 60 is the same as multiplying by (1/60), which is 0.016666667

That would still be a float calculation, but avoids division which might be harder than multiplication.

You also want to multiply by 10000 to eliminate the decimal point, so you can multiply by 167, which you could do as an integer multiplication.

You will need long variables for this to avoid losing precision in the position.

aarg:
Yes, you can use fixed point arithmetic.
But you should scale it up first by 10 to preserve 6 digit precision.

566050 * 10 /6 = 943416

Another way to do the same thing is to work with smaller units.

If I want meters and fractions, I use integer millimeters. I can display meters by printing a decimal point in the right place, same as I did on chalkboards and paper and still do.

Variable type signed long (32 bit) is good to +/- 2 billion. That gives you 9 places.
Variable type signed long long (64 bit) is good to 19 places.
If you need more there's Binary Coded Decimal and other methods to reach arbitrary lengths.

If you include the labels in your equations for what the numbers mean, it gets easier to see.

100 x 2 = 200 is harder to work with than
100 km/hr x 2 hrs = 200 km where the units are clear and we know that we can change them.

And PS, last thing, if you have the places to fit, do all you multiplies before the divisions.
With integers

12 * (500/150) = 36
(12 * 500) / 150 = 40

And last-last; % is the modulo operator, it returns remainders.

4 % 3 = 1

Why not using float? Other than the delay of floating point calculations, I'm trying to save as much as possible SRAM space, as I have a feeling that its size will be a show-stopper.

Q1: If you just use float math do you run out of RAM?
If so there are probably better places to optimize the code that this single operation

Q2: If you just use float math is it too slow?
If so you can use integer math but be aware that long math and float math are not too different in speed.

If you are really in a performance problem you might have a look at this thread (not for the faint of heart :wink:

Wow, I did not expect that many replies....

@PaulS: Obviously, I'm not a native English speaker, but trying hard to get my message across. And I'm sure you got the basic idea of my saying... BTW, what's wrong with a rats ass???? :smiley:

@michinyon: I'm not sure what you mean? How do I do that? Google Maps do not work with NMEA coordinates, do they?

@aarg: but 566050 * 10 /6 = 943416.6666666. Not sure I get you.... :frowning:

@goforSmoke: Thats what I'll be doing. reading the string and loading the degrees in an integer, but still I wanted to see if I can load the minutes onto two different Integers (one for the integral part and one for the decimal part).

@robtilaart: That remains to be seen, when the whole code is complete. There are lots of char arrays and string manipulation going on (at least I got rid of the Strings and using only char arrays now) and I have a feeling that eventually the 2KB SRAM will fill up.... Thus I'm saving from everywhere...

Thanks again,

nikosk:
... That remains to be seen, when the whole code is complete. There are lots of char arrays and string manipulation going on (at least I got rid of the Strings and using only char arrays now) and I have a feeling that eventually the 2KB SRAM will fill up.... Thus I'm saving from everywhere...

be sure to define variables const if the are constant, and for non mutable char arrays (texts for display) you can use the F() macro

Serial.println(F("Hello world")); // places the text in FLASH or program memory, using no RAM

robtillaart:
be sure to define variables const if the are constant, and for non mutable char arrays (texts for display) you can use the F() macro

Serial.println(F("Hello world")); // places the text in FLASH or program memory, using no RAM

Goes without saying :slight_smile: The F() macro is life saving...