real2str.inc 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1997 by Michael Van Canneyt,
  5. member of the Free Pascal development team
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. type
  13. treal_type = (rt_s64real,rt_s32real,rt_f32bit,rt_s80real,rt_s64bit);
  14. { corresponding to real single fixed extended and comp for i386 }
  15. {$ifdef i386}
  16. { bestreal = extended; still gives problems }
  17. bestreal = double;
  18. {$else i386}
  19. bestreal = single;
  20. {$endif i386}
  21. Procedure str_real (len,f : longint; d : bestreal; real_type :treal_type; var s : string);
  22. {
  23. These numbers are for the double type...
  24. At the moment these are mapped onto a double but this may change
  25. in the future !
  26. }
  27. var maxlen : longint; { Maximal length of string for float }
  28. minlen : longint; { Minimal length of string for float }
  29. explen : longint; { Length of exponent, including E and sign.
  30. Must be strictly larger than 2 }
  31. const
  32. maxexp = 1e+35; { Maximum value for decimal expressions }
  33. minexp = 1e-35; { Minimum value for decimal expressions }
  34. zero = '0000000000000000000000000000000000000000';
  35. var correct : longint; { Power correction }
  36. currprec : longint;
  37. roundcorr : bestreal;
  38. temp : string;
  39. power : string[10];
  40. sign : boolean;
  41. i : integer;
  42. dot : byte;
  43. begin
  44. case real_type of
  45. rt_s64real :
  46. begin
  47. maxlen:=23;
  48. minlen:=9;
  49. explen:=5;
  50. end;
  51. rt_s32real :
  52. begin
  53. maxlen:=16;
  54. minlen:=8;
  55. explen:=4;
  56. end;
  57. rt_f32bit :
  58. begin
  59. maxlen:=16;
  60. minlen:=8;
  61. explen:=4;
  62. end;
  63. rt_s80real :
  64. begin
  65. maxlen:=26;
  66. minlen:=10;
  67. explen:=6;
  68. end;
  69. rt_s64bit :
  70. begin
  71. maxlen:=22;
  72. minlen:=9;
  73. { according to TP (was 5) (FK) }
  74. explen:=6;
  75. end;
  76. end;
  77. { check parameters }
  78. { default value for length is -32767 }
  79. if len=-32767 then len:=maxlen;
  80. { determine sign. before precision, needs 2 less calls to abs() }
  81. sign:=d<0;
  82. { the creates a cannot determine which overloaded function to call
  83. if d is extended !!!
  84. we should prefer real_to_real on real_to_longint !!
  85. corrected in compiler }
  86. { d:=abs(d); this converts d to double so we loose precision }
  87. { for the same reason I converted d:=frac(d) to d:=d-int(d); (PM) }
  88. if sign then d:=-d;
  89. { determine precision : maximal precision is : }
  90. currprec:=maxlen-explen-3;
  91. { this is also the maximal number of decimals !!}
  92. if f>currprec then f:=currprec;
  93. { when doing a fixed-point, we need less characters.}
  94. if (f<0) or ((d>maxexp) or (d<minexp)) then
  95. begin
  96. { determine maximal number of decimals }
  97. if (len>=0) and (len<minlen) then len:=minlen;
  98. if (len>0) and (len<maxlen) then
  99. currprec:=len-explen-3;
  100. end;
  101. { convert to standard form. }
  102. correct:=0;
  103. if d>=10.0 then
  104. while d>=10.0 do
  105. begin
  106. d:=d/10.0;
  107. inc(correct);
  108. end
  109. else if (d<1) and (d<>0) then
  110. while d<1 do
  111. begin
  112. d:=d*10.0;
  113. dec(correct);
  114. end;
  115. { RoundOff }
  116. roundcorr:=0.5;
  117. if f<0 then
  118. for i:=1 to currprec do roundcorr:=roundcorr/10
  119. else
  120. for i:=1 to correct+f do roundcorr:=roundcorr/10;
  121. d:=d+roundcorr;
  122. { 0.99 + 0.05 > 10.0 ! Fix this by dividing the results >=10 first (PV) }
  123. if d>=10.0 then
  124. begin
  125. d:=d/10.0;
  126. inc(correct);
  127. end;
  128. { Now we have a standard expression : sign d *10^correct
  129. where 1<d<10 or d=0 ... }
  130. { get first character }
  131. if sign then
  132. temp:='-'
  133. else
  134. temp:=' ';
  135. temp:=temp+chr(ord('0')+trunc(d));
  136. d:=d-int(d);
  137. { Start making the string }
  138. for i:=1 to currprec do
  139. begin
  140. d:=d*10.0;
  141. temp:=temp+chr(ord('0')+trunc(d));
  142. d:=d-int(d);
  143. end;
  144. { Now we need two different schemes for the different
  145. representations. }
  146. if (f<0) or (correct>maxexp) then
  147. begin
  148. insert ('.',temp,3);
  149. str(abs(correct),power);
  150. if length(power)<explen-2 then
  151. power:=copy(zero,1,explen-2-length(power))+power;
  152. if correct<0 then power:='-'+power else power:='+'+power;
  153. temp:=temp+'E'+power;
  154. end
  155. else
  156. begin
  157. if not sign then
  158. begin
  159. delete (temp,1,1);
  160. dot:=2;
  161. end
  162. else
  163. dot:=3;
  164. { set zeroes and dot }
  165. if correct>=0 then
  166. begin
  167. if length(temp)<correct+dot+f then
  168. temp:=temp+copy(zero,1,correct+dot+f-length(temp));
  169. insert ('.',temp,correct+dot);
  170. end
  171. else
  172. begin
  173. correct:=abs(correct);
  174. insert(copy(zero,1,correct),temp,dot-1);
  175. insert ('.',temp,dot);
  176. end;
  177. {correct length to fit precision.}
  178. if f>0 then
  179. temp[0]:=chr(pos('.',temp)+f)
  180. else
  181. temp[0]:=chr(pos('.',temp)-1);
  182. end;
  183. if length(temp)<len then
  184. s:=space(len-length(temp))+temp
  185. else
  186. s:=temp;
  187. end;
  188. {
  189. $Log$
  190. Revision 1.3 1998-05-12 10:42:45 peter
  191. * moved getopts to inc/, all supported OS's need argc,argv exported
  192. + strpas, strlen are now exported in the systemunit
  193. * removed logs
  194. * removed $ifdef ver_above
  195. Revision 1.2 1998/04/07 22:40:46 florian
  196. * final fix of comp writing
  197. }