real2str.inc 6.6 KB

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