real2str.inc 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  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. {$ifdef DEFAULT_EXTENDED}
  17. bestreal = extended;
  18. {$else}
  19. bestreal = double;
  20. {$endif DEFAULT_EXTENDED}
  21. {$else i386}
  22. bestreal = single;
  23. {$endif i386}
  24. Procedure str_real (len,f : longint; d : bestreal; real_type :treal_type; var s : string);
  25. {
  26. These numbers are for the double type...
  27. At the moment these are mapped onto a double but this may change
  28. in the future !
  29. }
  30. var maxlen : longint; { Maximal length of string for float }
  31. minlen : longint; { Minimal length of string for float }
  32. explen : longint; { Length of exponent, including E and sign.
  33. Must be strictly larger than 2 }
  34. const
  35. maxexp = 1e+35; { Maximum value for decimal expressions }
  36. minexp = 1e-35; { Minimum value for decimal expressions }
  37. zero = '0000000000000000000000000000000000000000';
  38. var correct : longint; { Power correction }
  39. currprec : longint;
  40. roundcorr : bestreal;
  41. temp : string;
  42. power : string[10];
  43. sign : boolean;
  44. i : integer;
  45. dot : byte;
  46. begin
  47. case real_type of
  48. rt_s64real :
  49. begin
  50. maxlen:=23;
  51. minlen:=9;
  52. explen:=5;
  53. end;
  54. rt_s32real :
  55. begin
  56. maxlen:=16;
  57. minlen:=8;
  58. explen:=4;
  59. end;
  60. rt_f32bit :
  61. begin
  62. maxlen:=16;
  63. minlen:=8;
  64. explen:=4;
  65. end;
  66. rt_s80real :
  67. begin
  68. maxlen:=26;
  69. minlen:=10;
  70. explen:=6;
  71. end;
  72. rt_s64bit :
  73. begin
  74. maxlen:=22;
  75. minlen:=9;
  76. { according to TP (was 5) (FK) }
  77. explen:=6;
  78. end;
  79. end;
  80. { check parameters }
  81. { default value for length is -32767 }
  82. if len=-32767 then len:=maxlen;
  83. { determine sign. before precision, needs 2 less calls to abs() }
  84. sign:=d<0;
  85. { the creates a cannot determine which overloaded function to call
  86. if d is extended !!!
  87. we should prefer real_to_real on real_to_longint !!
  88. corrected in compiler }
  89. { d:=abs(d); this converts d to double so we loose precision }
  90. { for the same reason I converted d:=frac(d) to d:=d-int(d); (PM) }
  91. if sign then d:=-d;
  92. { determine precision : maximal precision is : }
  93. currprec:=maxlen-explen-3;
  94. { this is also the maximal number of decimals !!}
  95. if f>currprec then f:=currprec;
  96. { when doing a fixed-point, we need less characters.}
  97. if (f<0) or ( (d<>0) and ((d>maxexp) or (d<minexp))) then
  98. begin
  99. { determine maximal number of decimals }
  100. if (len>=0) and (len<minlen) then len:=minlen;
  101. if (len>0) and (len<maxlen) then
  102. currprec:=len-explen-3;
  103. end;
  104. { convert to standard form. }
  105. correct:=0;
  106. if d>=10.0 then
  107. while d>=10.0 do
  108. begin
  109. d:=d/10.0;
  110. inc(correct);
  111. end
  112. else if (d<1) and (d<>0) then
  113. while d<1 do
  114. begin
  115. d:=d*10.0;
  116. dec(correct);
  117. end;
  118. { RoundOff }
  119. roundcorr:=0.5;
  120. if f<0 then
  121. for i:=1 to currprec do roundcorr:=roundcorr/10
  122. else
  123. begin
  124. if correct+f<0 then
  125. begin
  126. for i:=1 to abs(correct+f) do
  127. roundcorr:=roundcorr*10;
  128. end
  129. else
  130. begin
  131. for i:=1 to correct+f do
  132. roundcorr:=roundcorr/10;
  133. end;
  134. end;
  135. d:=d+roundcorr;
  136. { 0.99 + 0.05 > 1.0 ! Fix this by dividing the results >=10 first (PV) }
  137. while (d>=10.0) do
  138. begin
  139. d:=d/10.0;
  140. inc(correct);
  141. end;
  142. { Now we have a standard expression : sign d *10^correct
  143. where 1<d<10 or d=0 ... }
  144. { get first character }
  145. if sign then
  146. temp:='-'
  147. else
  148. temp:=' ';
  149. temp:=temp+chr(ord('0')+trunc(d));
  150. d:=d-int(d);
  151. { Start making the string }
  152. for i:=1 to currprec do
  153. begin
  154. d:=d*10.0;
  155. temp:=temp+chr(ord('0')+trunc(d));
  156. d:=d-int(d);
  157. end;
  158. { Now we need two different schemes for the different
  159. representations. }
  160. if (f<0) or (correct>maxexp) then
  161. begin
  162. insert ('.',temp,3);
  163. str(abs(correct),power);
  164. if length(power)<explen-2 then
  165. power:=copy(zero,1,explen-2-length(power))+power;
  166. if correct<0 then power:='-'+power else power:='+'+power;
  167. temp:=temp+'E'+power;
  168. end
  169. else
  170. begin
  171. if not sign then
  172. begin
  173. delete (temp,1,1);
  174. dot:=2;
  175. end
  176. else
  177. dot:=3;
  178. { set zeroes and dot }
  179. if correct>=0 then
  180. begin
  181. if length(temp)<correct+dot+f then
  182. temp:=temp+copy(zero,1,correct+dot+f-length(temp));
  183. insert ('.',temp,correct+dot);
  184. end
  185. else
  186. begin
  187. correct:=abs(correct);
  188. insert(copy(zero,1,correct),temp,dot-1);
  189. insert ('.',temp,dot);
  190. end;
  191. {correct length to fit precision.}
  192. if f>0 then
  193. temp[0]:=chr(pos('.',temp)+f)
  194. else
  195. temp[0]:=chr(pos('.',temp)-1);
  196. end;
  197. if length(temp)<len then
  198. s:=space(len-length(temp))+temp
  199. else
  200. s:=temp;
  201. end;
  202. {
  203. $Log$
  204. Revision 1.11 1999-02-16 00:49:20 peter
  205. * fixed rounding when correct+f < 0
  206. Revision 1.10 1998/08/11 21:39:06 peter
  207. * splitted default_extended from support_extended
  208. Revision 1.9 1998/08/11 00:05:25 peter
  209. * $ifdef ver0_99_5 updates
  210. Revision 1.8 1998/08/10 15:56:30 peter
  211. * fixed 0_9_5 typo
  212. Revision 1.7 1998/08/08 12:28:12 florian
  213. * a lot small fixes to the extended data type work
  214. Revision 1.6 1998/07/18 17:14:22 florian
  215. * strlenint type implemented
  216. Revision 1.5 1998/07/13 21:19:10 florian
  217. * some problems with ansi string support fixed
  218. Revision 1.4 1998/06/18 08:15:33 michael
  219. + Fixed error when printing zero. len was calculated wron.
  220. Revision 1.3 1998/05/12 10:42:45 peter
  221. * moved getopts to inc/, all supported OS's need argc,argv exported
  222. + strpas, strlen are now exported in the systemunit
  223. * removed logs
  224. * removed $ifdef ver_above
  225. Revision 1.2 1998/04/07 22:40:46 florian
  226. * final fix of comp writing
  227. }