Recent

Author Topic: Acessing the exponent of a floating point  (Read 4176 times)

Stephan

  • New Member
  • *
  • Posts: 19
Acessing the exponent of a floating point
« on: October 08, 2016, 03:36:45 pm »
Is there a better/faster way to get the exponent from a floating point number than to do something like this:
Code: Pascal  [Select][+][-]
  1. exponent:= floor(log10(fp_number));
?
Which also only works if the number is greater than zero.

molly

  • Hero Member
  • *****
  • Posts: 2330
Re: Acessing the exponent of a floating point
« Reply #1 on: October 08, 2016, 03:45:22 pm »
Perhaps you could make use of TSingleRec and/or TDoubleRec ? Not saying it is better/faster.

edit: e.g. something like this
Code: Pascal  [Select][+][-]
  1. var
  2.   s : single;
  3.   d : double;
  4.   se, de: longint;
  5. begin
  6.   s := ...;
  7.   d := ...;
  8.   se := TSingleRec(s).Exponent;
  9.   de := TDoubleRec(d).Exponent;
  10. end;
« Last Edit: October 08, 2016, 03:53:43 pm by molly »

wp

  • Hero Member
  • *****
  • Posts: 13484
Re: Acessing the exponent of a floating point
« Reply #2 on: October 08, 2016, 04:08:19 pm »
Perhaps you could make use of TSingleRec and/or TDoubleRec ? Not saying it is better/faster.
No, this returns the dual exponent (base 2), but Stephan wants the decadic exponent (base 10).

Stephan, in order to be able to handle negative numbers, I use the absolute value in the log10. The sign of the value would show up in the mantissa, but not in the exponent.

Code: Pascal  [Select][+][-]
  1.   exponent:= floor(log10(abs(fp_number)));

Another method which I've seen sometimes takes advantage of a string conversion:
Code: Pascal  [Select][+][-]
  1. var st: String;
  2.   Str(fp_number, st);
  3.   exponent := StrToInt(copy(st, pos('E', st)+1, MaxInt));

molly

  • Hero Member
  • *****
  • Posts: 2330
Re: Acessing the exponent of a floating point
« Reply #3 on: October 08, 2016, 04:12:25 pm »
No, this returns the dual exponent (base 2), but Stephan wants the decadic exponent (base 10).
Yups, sorry for that. I noticed too late.

wp

  • Hero Member
  • *****
  • Posts: 13484
Re: Acessing the exponent of a floating point
« Reply #4 on: October 08, 2016, 05:16:35 pm »
I checked the speed of the "math" and the "string" method and found that the "string" method is slower by more than a factor 10:
Code: Pascal  [Select][+][-]
  1. program Project1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. uses
  6.   math, sysutils;
  7.  
  8. function ExponentMath(AValue: Double): Integer;
  9. begin
  10.   Result := floor(log10(abs(AValue)));
  11. end;
  12.  
  13. function ExponentStr(AValue: Double): Integer;
  14. var
  15.   s: String;
  16. begin
  17.   Str(AValue, s);
  18.   Result := StrToInt(copy(s, pos('E', s)+1, MaxInt));
  19. end;
  20.  
  21. const
  22.   NUM_TESTS = 1000000;
  23.  
  24. var
  25.   t: TDateTime;
  26.   i, j: Integer;
  27.   Value: Double;
  28. begin
  29.   Randomize;
  30.  
  31.   for j:=0 to 10 do begin
  32.     Value := Random * Power(10.0, random(20)-10) * (Random(2)*2 - 1);
  33.     WriteLn('Value = ', value);
  34.  
  35.     t := now;
  36.     for i:=1 to NUM_TESTS do
  37.       ExponentMath(Value);
  38.     WriteLn(Format('ExponentMath --> %.0f ms', [(Now - t) * (24*60*60*1000)]));
  39.  
  40.     t := now;
  41.     for i:=1 to NUM_TESTS do
  42.       ExponentStr(Value);
  43.     WriteLn(Format('ExponentStr  --> %.0f ms', [(Now - t) * (24*60*60*1000)]));
  44.  
  45.     WriteLn;
  46.   end;
  47.  
  48.   WriteLn('Finished.');
  49.   ReadLn;
  50. end.

Stephan

  • New Member
  • *
  • Posts: 19
Re: Acessing the exponent of a floating point
« Reply #5 on: October 08, 2016, 05:21:46 pm »
Perhaps you could make use of TSingleRec and/or TDoubleRec ? Not saying it is better/faster.
No, this returns the dual exponent (base 2), but Stephan wants the decadic exponent (base 10).
Interesting never the less. Need to keep that in mind for future projects. Might be useful.

Quote
Stephan, in order to be able to handle negative numbers, I use the absolute value in the log10. The sign of the value would show up in the mantissa, but not in the exponent.

Code: Pascal  [Select][+][-]
  1.   exponent:= floor(log10(abs(fp_number)));
Did that, but you still need to handle zero separately.

Quote
Another method which I've seen sometimes takes advantage of a string conversion:
Code: Pascal  [Select][+][-]
  1. var st: String;
  2.   Str(fp_number, st);
  3.   exponent := StrToInt(copy(st, pos('E', st)+1, MaxInt));
I'm seriously considering something like this! Neither fast nor elegant, but at least the error handling has been done... hopefully.

Thanks guys (and girls?). You're fast.

wp

  • Hero Member
  • *****
  • Posts: 13484
Re: Acessing the exponent of a floating point
« Reply #6 on: October 08, 2016, 05:42:46 pm »
you still need to handle zero separately. (...) but at least the error handling has been done... hopefully.

What is the problem of checking for zero in a function?

Code: Pascal  [Select][+][-]
  1. function Exponent(AValue: Double): Integer;
  2. begin
  3.   if AValue = 0.0 then
  4.     Result := 0
  5.   else
  6.     Result := floor(log10(abs(AValue)));
  7. end;

 

TinyPortal © 2005-2018