Re: Delphi angles, degrees, minutes, seconds
Posted by webmaster Guido on December 23, 2002 at 18:11:52:
In Reply to: Re: Delphi Books & Math Unit posted by Lionel on December 16, 2002 at 04:07:49:
procedure TForm1.btnCalculateClick(Sender: TObject); var Degrees, Minutes, Error: integer; DD_MMSS, DecFraction1, MM_SS, DecFraction2, Seconds, DecimalDegrees: real; begin Val(Edit1.Text, DD_MMSS, Error); // try to convert text to real number if Error <> 0 then // error during conversion? ShowMessage('Invalid format, please enter the angle as DD.MMSS') else begin Degrees := Trunc(DD_MMSS); // part before decimal separator DecFraction1 := Frac(DD_MMSS); // remove part before dec. separator MM_SS := DecFraction1 * 100; // "shift left" 2 decimal places Minutes := Trunc(MM_SS); // part before dec. separator DecFraction2 := Frac(MM_SS); // remove part before dec. separator Seconds := DecFraction2 * 100; // "shift left" 2 decimal places DecimalDegrees := Degrees + Minutes / 60 + Seconds / 3600; lblDeg.Caption := IntToStr(Degrees); lblMin.Caption := IntToStr(Minutes); lblSec.Caption := FloatToStr(Seconds); lblDecDeg.Caption := FloatToStr(DecimalDegrees); end; end;
This is only correct for some input values, but it's wrong for most inputs. For example, if you input 2.0100:
That's because for most inputs, the result of the Frac function is either just a little bit too big or too small (because internally the program works with binary numbers, and most *decimal* fractions numbers can not be converted exactly to *binary* fractions).
But if we loose a minute in this way, we get it back in the seconds part, because of these two lines:
So, back to the drawing table. You could adapt the current code by rounding the numbers to a certain number of decimal places, at some critical points in the code. But that would require quite some more analysis, and finally it would defeat the original purpose, a short and simple conversion method.
The most reliable way to work with this "DD.MMSS" format, is to extract the *strings* for the degrees, minutes and seconds, next convert these 3 strings to 3 numbers. That's more code, because it would also require some more error checking, and you would have to set some rules as to what would happen if you enter less than 4 digits in the decimal part: give an error message, or accept this? For example, "10.2" would mean 20 minutes (not 2), and "10.203" would mean 30 seconds (not 3).
I've sent you a personal email, with an example project that demonstrates the initial code plus a better method.
Note for interested readers:
In the little program above, a special "custom" shorthand notation DD.MMSS is used. Attention, this is not an official notation! It's used only as a method for quickly entering angles with a minimal amount of keystrokes!
So, remember that entering 10.4518 in the edit-box does NOT mean: