home *** CD-ROM | disk | FTP | other *** search
/ Crawly Crypt Collection 2 / crawlyvol2.bin / program / pascal / passrc / rstrval.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1985-11-18  |  8.1 KB  |  354 lines

  1. { -----------------------------------------------------------------------------
  2.  
  3.                                  NOTICE:
  4.  
  5.       THESE MATERIALS are UNSUPPORTED by OSS!  If you do not understand how to
  6.       use them do not contact OSS for help!  We will not teach you how to 
  7.       program in Pascal.  If you find an error in these materials, feel free
  8.       to SEND US A LETTER explaining the error, and how to fix it.
  9.  
  10.       THE BOTTOM LINE:
  11.  
  12.          Use it, enjoy it, but you are on your own when using these materials!
  13.  
  14.  
  15.                                DISCLAIMER:
  16.  
  17.       OSS makes no representations or warranties with respect to the contents
  18.       hereof and specifically disclaim all warranties of merchantability or
  19.       fitness for any particular purpose.   This document is subject to change
  20.       without notice.
  21.       
  22.       OSS provides these materials for use with Personal Pascal.  Use them in
  23.       any way you wish.
  24.  
  25.    -------------------------------------------------------------------------- }
  26.  
  27.  
  28. {*  THIS IS A PROGRAM, TAKE OUT THE MAIN ROUTINE TO USE JUST THE FUNCTIONS *}
  29.  
  30. Program LalaBlahLala(InThoughTheOutDoor,OutThroughTheInDoor);
  31.  
  32. Var
  33.   TestSt:  String;
  34.   TestRl:  Real;
  35.  
  36.  
  37. {***
  38.  *   Floating Point Conversion routines.
  39.  *   From Real to String and String to Real
  40.  *
  41.  *   By Kevin L. McGrath
  42.  ***}
  43.  
  44. PROCEDURE Str(Value: Real; VAR St: String);
  45.  
  46. {* Notes:
  47.  *   This routine is only accurate up to 9 digits becuase of the LongTrunc.
  48.  *   It HAD rounding errors, but they are now fixed (with the LongTrunc)
  49.  *
  50.  * O.S.S. Pascals Floating Point Format:
  51.  *   This is just a guess, but here goes...
  52.  *   One byte of exponent biased by 128 to give a +38 to -38 range.
  53.  *   Fourty bits of mantissa to give 11 digits of accuracy, One bit sign.
  54.  *   Most floating points are normalized to the left, with the point between
  55.  *   the most significant bit of the mantissa and the second most, so I think
  56.  *   this is two.  To find out, just plug out a routine that has a pointer
  57.  *   to a real, coerce's it into a pointer to a record structure of byte like
  58.  *   this:
  59.  *     Record
  60.  *       Exponent:      Byte;
  61.  *       MantissaOne:   Long;
  62.  *       MantissaTwo:   Long;
  63.  *       MantissaThree: Long;
  64.  *     End;
  65.  *   then you can extract the exponent and mantissa just by doing a
  66.  *   "Ptr.Exponent" or somethin like that.  Well, I haven't had time to get
  67.  *   that fancy with this, but I have used this routine and am sure it works.
  68.  *   Hope you guys at O.S.S. can vert it to some kind of normal ASM function!
  69.  *      Good Luck...   (Nice Compiler)
  70.  *      Call me if there are any probs, dig?
  71.  *}
  72.  
  73.  
  74. Const
  75.   Max_Digits    = 09;
  76.   Max_Exponent  = 38;
  77.  
  78. Var
  79.   Val:          Real;
  80.   TempInt,
  81.   Sig_Digits,
  82.   Dec_Exp,
  83.   I:            Integer;
  84.   Digits:       String;
  85.  
  86. Begin
  87.   Val := Abs(Value);
  88.   Dec_Exp := 0;
  89.  
  90.   {* Get the exponent without Natural Log (Ln doesn't seem to work fer me) *}
  91.  
  92.   If (Val < 1) And (Val > 0) Then
  93.   Begin
  94.     For I := 0 To (Max_Exponent-1) Do
  95.       If (Val < (1/PwrOfTen(I))) And (Val >= (1/PwrOfTen(I+1))) Then
  96.         Dec_Exp := -(I+1);
  97.     Val := Val * PwrOfTen(Abs(Dec_Exp)-1);
  98.   End
  99.   Else
  100.   Begin
  101.     For I := 0 To (Max_Exponent-1) Do
  102.       If (Val >= PwrOfTen(I)) And (Val < PwrOfTen(I+1)) Then
  103.         Dec_Exp := I;
  104.     Val := Val / PwrOfTen(Dec_Exp+1);
  105.   End;
  106.  
  107. { Get decimal digits by stripping }
  108.  
  109.   Digits := '';
  110.   St := '';
  111.  
  112.   For I := Max_Digits DownTo 1 Do
  113.   Begin
  114.     { Take care of rounding problems }
  115.  
  116.     Val := Long_Trunc(Val*PwrOfTen(I)+0.5)/PwrOfTen(I);
  117.  
  118.     Val := Val*10.0;
  119.     Digits := ConCat(Digits,Chr(48+Trunc(Val)));
  120.     Val := Val-Trunc(Val);
  121.  
  122.     { Take care of rounding problems }
  123.  
  124.     Val := Long_Trunc(Val*PwrOfTen(I)+0.5)/PwrOfTen(I);
  125.  
  126.   End;
  127.  
  128. { Format and put result in St }
  129. { Put sign }
  130.  
  131.   If Value < 0 Then St := '-';
  132.  
  133. { Compute significant digits }
  134.  
  135.   Sig_Digits := Max_Digits;
  136.   I := Max_Digits - 1;
  137.   While ((Digits[I]='0') And (I>0)) Do
  138.   Begin
  139.     Sig_Digits := Sig_Digits - 1;
  140.     I := I - 1;
  141.   End;
  142.   Sig_Digits := Sig_Digits - 1;
  143.  
  144. { Put in exponential or non-exonential }
  145.  
  146.   If ((Sig_Digits-Max_Digits)<=Dec_Exp) And (Dec_Exp<=Max_Digits) Then
  147.   Begin
  148.     { Non-exponental form }
  149.     { Put decimal point and leading zeros for numbers with negative exponents }
  150.  
  151.     If Dec_Exp < 0 Then
  152.     Begin
  153.       St := ConCat(St,'.');
  154.       For I := 1 To -Dec_Exp-1 Do
  155.         St := ConCat(St,'0');
  156.     End;
  157.  
  158.     { Put significant digits }
  159.  
  160.     St := ConCat(St,Digits[1]);
  161.     For I := 1 To Sig_Digits-1 Do
  162.     Begin
  163.       If Dec_Exp = 0 Then
  164.         St := ConCat(St,'.');
  165.       St := ConCat(St,Digits[I+1]);
  166.       Dec_Exp := Dec_Exp - 1;
  167.     End;
  168.  
  169.     { Put trailing zeros }
  170.  
  171.     While Dec_Exp > 0 Do
  172.     Begin
  173.       St := ConCat(St,'0');
  174.       Dec_Exp := Dec_Exp - 1;
  175.     End;
  176.   End
  177.   Else
  178.   Begin
  179.     { Exponental form }
  180.     { Put first digit }
  181.  
  182.     St := ConCat(St,Digits[1]);
  183.  
  184.     { Put decimal point }
  185.  
  186.     If Sig_Digits > 1 Then
  187.       St := ConCat(St,'.');
  188.  
  189.     { Put remaining significant digits }
  190.  
  191.     For I := 1 To (Sig_Digits - 1) Do
  192.       St := ConCat(St,Digits[I+1]);
  193.  
  194.     { Put the 'E' for the exponent }
  195.  
  196.     St := ConCat(St,'E');
  197.  
  198.     { Put exponents sign }
  199.  
  200.     If Dec_Exp >= 0 Then
  201.       St := ConCat(St,'+')
  202.     Else
  203.     Begin
  204.       St := ConCat(St,'-');
  205.       Dec_Exp := Abs(Dec_Exp);
  206.     End;
  207.  
  208.     { Put the exponent }
  209.  
  210.     If Dec_Exp >= 10 Then
  211.     Begin
  212.       St := ConCat(St,Chr(48+(Dec_Exp Div 10)));
  213.       St := ConCat(St,Chr(48+Dec_Exp-((Dec_Exp Div 10) * 10)));
  214.     End
  215.     Else
  216.     Begin
  217.       St := ConCat(St,'0');
  218.       St := ConCat(St,Chr(48+Dec_Exp));
  219.     End;
  220.   End;
  221. End;
  222.  
  223.  
  224. FUNCTION Val( St: String): Real;
  225.  
  226. Const
  227.   Max_Digits    = 09;
  228.  
  229. Var
  230.   Dec_Exp,
  231.   Exp_Value,
  232.   Count,
  233.   Position:     Integer;
  234.   Chr:          Char;
  235.   Result:       Real;
  236.   Dec_Sign,
  237.   Exp_Sign:     Boolean;
  238.  
  239.   PROCEDURE Add_Digit;
  240.  
  241.   Begin
  242.     Result := (Result * 10) + (Ord(Chr) & $0F);
  243.   End;
  244.  
  245.   PROCEDURE Read_Chr;
  246.  
  247.   Begin
  248.     Position := Position + 1;
  249.     If Position > Length(St) Then
  250.       Chr := 'X'
  251.     Else
  252.       Chr := St[Position];
  253.   End;
  254.  
  255. Begin
  256.   Position := 0;
  257.   Read_Chr;
  258.   Result := 0.0;
  259.  
  260. { Get sign }
  261.  
  262.   Dec_Sign := False;
  263.   If Chr = '+' Then Read_Chr;
  264.   If Chr = '-' Then
  265.   Begin
  266.     Read_Chr;
  267.     Dec_Sign := True;
  268.   End;
  269.  
  270. { Get digits to left of decimal point }
  271.  
  272.   Dec_Exp := 0;
  273.   Count := Max_Digits;
  274.   While ('0' <= Chr) And (Chr <= '9') Do
  275.   Begin
  276.     If Count > 0 Then
  277.     Begin
  278.       Add_Digit;
  279.       Count := Count - 1;
  280.     End
  281.     Else
  282.       Dec_Exp := Dec_Exp + 1;
  283.     Read_Chr;
  284.   End;
  285.  
  286. { Get digits to the right of decimal point }
  287.  
  288.   If Chr = '.' Then
  289.   Begin
  290.     Read_Chr;
  291.     While ('0' <= Chr) And (Chr <= '9') Do
  292.     Begin
  293.       If Count > 0 Then
  294.       Begin
  295.         Add_Digit;
  296.         Dec_Exp := Dec_Exp - 1;
  297.         Count := Count - 1;
  298.       End;
  299.       Read_Chr;
  300.     End;
  301.   End;
  302.  
  303. { Get exponent part }
  304.  
  305.   If (Chr = 'E') Or (Chr = 'e') Then
  306.   Begin
  307.     Read_Chr;
  308.     Exp_Sign := False;
  309.     If Chr = '+' Then Read_Chr;
  310.     If Chr = '-' Then
  311.     Begin
  312.       Read_Chr;
  313.       Exp_Sign := True;
  314.     End;
  315.     Exp_Value := 0;
  316.     If ('0'<=Chr) And (Chr<='9') Then Exp_Value := (Ord(Chr) & $0F)*10;
  317.     Read_Chr;
  318.     If ('0'<=Chr) And (Chr<='9') Then Exp_Value := Exp_Value+(Ord(Chr) & $0F);
  319.     If (Chr = 'X') And (Exp_Value >= 10) Then Exp_Value := Exp_Value Div 10;
  320.     If Exp_Sign Then
  321.       Dec_Exp := Dec_Exp - Exp_Value
  322.     Else
  323.       Dec_Exp := Dec_Exp + Exp_Value;
  324.   End;
  325.  
  326. { Multiply or divide Result by power of 10 specified by Dec_Exp }
  327.  
  328.   If Dec_Exp > 0 Then
  329.     Result := Result * PwrOfTen(Dec_Exp)
  330.   Else
  331.     Result := Result / PwrOfTen(Abs(Dec_Exp));
  332.  
  333.   If Dec_Sign Then Result := -Result;
  334.  
  335.   Val := Result;
  336.  
  337. End;
  338.  
  339.  
  340. {*  MAIN ROUTINE  *}
  341.  
  342. Begin
  343.   TestRl := 0.0;
  344.   While (TestRl <> 9.0) do
  345.   Begin
  346.     WriteLn('Test for Val and Str. Enter a "9" to stop.');
  347.     Write('Enter a number:');
  348.     ReadLn(TestSt);
  349.     TestRl := Val(TestSt);
  350.     Str(TestRl,TestSt);
  351.     WriteLn('Real number as a string:',TestSt);
  352.   End;
  353. End.
  354.