real2str.inc 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  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. { See symdefh.inc tfloattyp }
  14. treal_type = (rt_s32real,rt_s64real,rt_s80real,rt_c64bit,rt_f16bit,rt_f32bit);
  15. { corresponding to single double extended fixed comp for i386 }
  16. const
  17. { do not use real constants else you get rouding errors }
  18. i10 = 10;
  19. i2 = 2;
  20. i1 = 1;
  21. Procedure str_real (len,f : longint; d : ValReal; 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 : Valreal;
  38. temp : string;
  39. power : string[10];
  40. sign : boolean;
  41. i : integer;
  42. dot : byte;
  43. currp : pchar;
  44. begin
  45. case real_type of
  46. rt_s32real :
  47. begin
  48. maxlen:=16;
  49. minlen:=8;
  50. explen:=4;
  51. end;
  52. rt_s64real :
  53. begin
  54. maxlen:=23;
  55. minlen:=9;
  56. explen:=5;
  57. end;
  58. rt_s80real :
  59. begin
  60. maxlen:=26;
  61. minlen:=10;
  62. explen:=6;
  63. end;
  64. rt_c64bit :
  65. begin
  66. maxlen:=22;
  67. minlen:=9;
  68. { according to TP (was 5) (FK) }
  69. explen:=6;
  70. end;
  71. rt_f16bit :
  72. begin
  73. maxlen:=16;
  74. minlen:=8;
  75. explen:=4;
  76. end;
  77. rt_f32bit :
  78. begin
  79. maxlen:=16;
  80. minlen:=8;
  81. explen:=4;
  82. end;
  83. end;
  84. { check parameters }
  85. { default value for length is -32767 }
  86. if len=-32767 then
  87. 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
  97. d:=-d;
  98. { determine precision : maximal precision is : }
  99. currprec:=maxlen-explen-3;
  100. { this is also the maximal number of decimals !!}
  101. if f>currprec then
  102. f:=currprec;
  103. { when doing a fixed-point, we need less characters.}
  104. if (f<0) or ( (d<>0) and ((d>maxexp) or (d<minexp))) then
  105. begin
  106. { determine maximal number of decimals }
  107. if (len>=0) and (len<minlen) then
  108. len:=minlen;
  109. if (len>0) and (len<maxlen) then
  110. currprec:=len-explen-3;
  111. end;
  112. { convert to standard form. }
  113. correct:=0;
  114. if d>=i10 then
  115. while d>=i10 do
  116. begin
  117. d:=d/i10;
  118. inc(correct);
  119. end
  120. else if (d<1) and (d<>0) then
  121. while d<1 do
  122. begin
  123. d:=d*i10;
  124. dec(correct);
  125. end;
  126. { RoundOff }
  127. roundcorr:=extended(i1)/extended(i2);
  128. if f<0 then
  129. for i:=1 to currprec do roundcorr:=roundcorr/i10
  130. else
  131. begin
  132. if correct+f<0 then
  133. begin
  134. for i:=1 to abs(correct+f) do
  135. roundcorr:=roundcorr*i10;
  136. end
  137. else
  138. begin
  139. for i:=1 to correct+f do
  140. roundcorr:=roundcorr/i10;
  141. end;
  142. end;
  143. d:=d+roundcorr;
  144. { 0.99 + 0.05 > 1.0 ! Fix this by dividing the results >=10 first (PV) }
  145. while (d>=10.0) do
  146. begin
  147. d:=d/i10;
  148. inc(correct);
  149. end;
  150. { Now we have a standard expression : sign d *10^correct
  151. where 1<d<10 or d=0 ... }
  152. { get first character }
  153. currp:=pchar(@temp[1]);
  154. if sign then
  155. currp^:='-'
  156. else
  157. currp^:=' ';
  158. inc(currp);
  159. currp^:=chr(ord('0')+trunc(d));
  160. inc(currp);
  161. d:=d-int(d);
  162. { Start making the string }
  163. for i:=1 to currprec do
  164. begin
  165. d:=d*i10;
  166. currp^:=chr(ord('0')+trunc(d));
  167. inc(currp);
  168. d:=d-int(d);
  169. end;
  170. temp[0]:=chr(currp-pchar(@temp[1]));
  171. { Now we need two different schemes for the different
  172. representations. }
  173. if (f<0) or (correct>maxexp) then
  174. begin
  175. insert ('.',temp,3);
  176. str(abs(correct),power);
  177. if length(power)<explen-2 then
  178. power:=copy(zero,1,explen-2-length(power))+power;
  179. if correct<0 then
  180. power:='-'+power
  181. else
  182. power:='+'+power;
  183. temp:=temp+'E'+power;
  184. end
  185. else
  186. begin
  187. if not sign then
  188. begin
  189. delete (temp,1,1);
  190. dot:=2;
  191. end
  192. else
  193. dot:=3;
  194. { set zeroes and dot }
  195. if correct>=0 then
  196. begin
  197. if length(temp)<correct+dot+f then
  198. temp:=temp+copy(zero,1,correct+dot+f-length(temp));
  199. insert ('.',temp,correct+dot);
  200. end
  201. else
  202. begin
  203. correct:=abs(correct);
  204. insert(copy(zero,1,correct),temp,dot-1);
  205. insert ('.',temp,dot);
  206. end;
  207. { correct length to fit precision }
  208. if f>0 then
  209. temp[0]:=chr(pos('.',temp)+f)
  210. else
  211. temp[0]:=chr(pos('.',temp)-1);
  212. end;
  213. if length(temp)<len then
  214. s:=space(len-length(temp))+temp
  215. else
  216. s:=temp;
  217. end;
  218. {
  219. $Log$
  220. Revision 1.14 1999-08-03 21:58:44 peter
  221. * small speed improvements
  222. Revision 1.13 1999/05/06 09:05:12 peter
  223. * generic write_float str_float
  224. Revision 1.12 1999/03/10 21:49:02 florian
  225. * str and val for extended use now int constants to minimize
  226. rounding error
  227. Revision 1.11 1999/02/16 00:49:20 peter
  228. * fixed rounding when correct+f < 0
  229. Revision 1.10 1998/08/11 21:39:06 peter
  230. * splitted default_extended from support_extended
  231. Revision 1.9 1998/08/11 00:05:25 peter
  232. * $ifdef ver0_99_5 updates
  233. Revision 1.8 1998/08/10 15:56:30 peter
  234. * fixed 0_9_5 typo
  235. Revision 1.7 1998/08/08 12:28:12 florian
  236. * a lot small fixes to the extended data type work
  237. Revision 1.6 1998/07/18 17:14:22 florian
  238. * strlenint type implemented
  239. Revision 1.5 1998/07/13 21:19:10 florian
  240. * some problems with ansi string support fixed
  241. Revision 1.4 1998/06/18 08:15:33 michael
  242. + Fixed error when printing zero. len was calculated wron.
  243. Revision 1.3 1998/05/12 10:42:45 peter
  244. * moved getopts to inc/, all supported OS's need argc,argv exported
  245. + strpas, strlen are now exported in the systemunit
  246. * removed logs
  247. * removed $ifdef ver_above
  248. Revision 1.2 1998/04/07 22:40:46 florian
  249. * final fix of comp writing
  250. }