real2str.inc 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  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. for i:=1 to correct+f do roundcorr:=roundcorr/10;
  124. d:=d+roundcorr;
  125. { 0.99 + 0.05 > 10.0 ! Fix this by dividing the results >=10 first (PV) }
  126. if d>=10.0 then
  127. begin
  128. d:=d/10.0;
  129. inc(correct);
  130. end;
  131. { Now we have a standard expression : sign d *10^correct
  132. where 1<d<10 or d=0 ... }
  133. { get first character }
  134. if sign then
  135. temp:='-'
  136. else
  137. temp:=' ';
  138. temp:=temp+chr(ord('0')+trunc(d));
  139. d:=d-int(d);
  140. { Start making the string }
  141. for i:=1 to currprec do
  142. begin
  143. d:=d*10.0;
  144. temp:=temp+chr(ord('0')+trunc(d));
  145. d:=d-int(d);
  146. end;
  147. { Now we need two different schemes for the different
  148. representations. }
  149. if (f<0) or (correct>maxexp) then
  150. begin
  151. insert ('.',temp,3);
  152. str(abs(correct),power);
  153. if length(power)<explen-2 then
  154. power:=copy(zero,1,explen-2-length(power))+power;
  155. if correct<0 then power:='-'+power else power:='+'+power;
  156. temp:=temp+'E'+power;
  157. end
  158. else
  159. begin
  160. if not sign then
  161. begin
  162. delete (temp,1,1);
  163. dot:=2;
  164. end
  165. else
  166. dot:=3;
  167. { set zeroes and dot }
  168. if correct>=0 then
  169. begin
  170. if length(temp)<correct+dot+f then
  171. temp:=temp+copy(zero,1,correct+dot+f-length(temp));
  172. insert ('.',temp,correct+dot);
  173. end
  174. else
  175. begin
  176. correct:=abs(correct);
  177. insert(copy(zero,1,correct),temp,dot-1);
  178. insert ('.',temp,dot);
  179. end;
  180. {correct length to fit precision.}
  181. if f>0 then
  182. temp[0]:=chr(pos('.',temp)+f)
  183. else
  184. temp[0]:=chr(pos('.',temp)-1);
  185. end;
  186. if length(temp)<len then
  187. s:=space(len-length(temp))+temp
  188. else
  189. s:=temp;
  190. end;
  191. {
  192. $Log$
  193. Revision 1.10 1998-08-11 21:39:06 peter
  194. * splitted default_extended from support_extended
  195. Revision 1.9 1998/08/11 00:05:25 peter
  196. * $ifdef ver0_99_5 updates
  197. Revision 1.8 1998/08/10 15:56:30 peter
  198. * fixed 0_9_5 typo
  199. Revision 1.7 1998/08/08 12:28:12 florian
  200. * a lot small fixes to the extended data type work
  201. Revision 1.6 1998/07/18 17:14:22 florian
  202. * strlenint type implemented
  203. Revision 1.5 1998/07/13 21:19:10 florian
  204. * some problems with ansi string support fixed
  205. Revision 1.4 1998/06/18 08:15:33 michael
  206. + Fixed error when printing zero. len was calculated wron.
  207. Revision 1.3 1998/05/12 10:42:45 peter
  208. * moved getopts to inc/, all supported OS's need argc,argv exported
  209. + strpas, strlen are now exported in the systemunit
  210. * removed logs
  211. * removed $ifdef ver_above
  212. Revision 1.2 1998/04/07 22:40:46 florian
  213. * final fix of comp writing
  214. }