Formatted output of real numbers.
One of the problems, that you encounter, when writing math or scientific applications, is the display of the results. What I mean, is the display of real numbers, having none or several significant decimal digits, and you, in your application not wanting to display them all, but only 2 or 3. Free Pascal provides two real to string conversion functions:
- FloatToStr converts the number to a string without formatting. Thus 1.23456 will be displayed as 1.23456 and 3.14 will be as 3.14. Problem: Possible display of more decimal digits, that you actually want.
- FloatToStrF converts the number to a string with formatting, one of the function's arguments being the format; e.g. ffFixed for fixed point format, or ffExponent for scientific notation. Double problem:
1. If the number is to small to be displayed with the format used, you will get a 0 displayed. E.g. Displaying numbers as fixed point format with a precision of 2 can only correctly display numbers with absolute value greater than or equal to 0.01; 0.009 for example being displayed as 0.
2. The number of decimal digits displayed is fixed, what means that insignificant zeros are also displayed. No issue, but results like 1.200 or 4.00 don't really look nice.
In my Free Pascal applications, I normally use a custom function RFormat to solve these problems. I tried several approaches, working more or less well. Finally, I think
to have found the code, that should work fine in all circumstances. The idea is a function, that has as arguments the number to convert and the number of decimal
digits to display. It should use scientific notation, if the number is to small to be displayed for the decimal digits given and should use fixed point format (with
dropping of the insignificant decimal digits) otherwise. Checking if the number may be correctly displayed is easy: Any number with absolute value greater than
10-n may be correctly shown with n decimal digits. Using FloatToStrF to display the fixed point number is not an option; as said
above, this function always displays exactly n decimal digits. If you have a look at the source code of my various applications, you see that I tried several ways to
suppress the insignificant decimal digits. And only now, while writing my TimerCircuits555 application, that I realize, that in fact there
is a very simple possibility.
The trick consists in rounding the number to the given number of decimal digits and then using the FloatToStr function,
that by default, suppresses the non significant zeros. How to do to round a real to n decimal digits? Just multiply it by 10n, use the Round function to convert it to an integer, then divide this integer by 10n.
Example (n = 2): If R = 12.3456 then Round(100 * R) = 1235 and 1235 / 100 = 12.35. And using FloatToStr, this is displayed 12.35 as 1.2 would
be displayed as 1.2 and 1 as 1 (and not 1.20 resp. 1.00, as would be with FloatToStrF).
A little problem here: Pascal has no build-in power function. Two possibilities: 1. Including the math unit. 2. Writing our own power function:
var
I: Integer;
Pow: Real;
begin
Pow := 1;
for I := 1 to Abs(N) do
Pow *= R;
if N < 0 then
Pow := 1 / Pow;
Result := Pow;
end;
And finally, the real number formatting function, as described above:
var
R0: Real;
SR: string;
begin
SR := '';
if R = 0 then
SR := '0'
else begin
if F >= 0 then begin
R0 := Round(R * Power(10, F)) / Power(10, F);
if Abs(R0) < Power(10, -F) then
SR := FloatToStrF(R, ffExponent, F, 0)
else
SR := FloatToStr(R0);
end;
end;
Result := SR;
end;
If you find this text helpful, please, support me and this website by signing my guestbook.