real2str.inc 6.6 KB

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