home *** CD-ROM | disk | FTP | other *** search
- /***
- *
- * Num.prg
- * Sample user-defined functions for manipulating numbers
- *
- * Copyright, Nantucket Corporation, 1990
- *
- * NOTE: compile with /n/w/a/m
- */
-
-
- /***
- * BaseToBase( <cInString>, <nInBase>, <nOutBase> ) --> cNewBaseValue
- * Transform a string of a number from one base to another
- * within the base range of 2 to 36
- *
- * Jake Jacob and Flemming Ho
- *
- * Note: Compile with /dNOARGCHECK to suppress argument checking
- *
- */
- FUNCTION BaseToBase( cInString, nInBase, nOutBase )
- LOCAL DIGITS := "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ", cNewBaseValue := ""
- LOCAL i, DecPos, IntValue := 0, FracValue := 0.000000000000000000
- LOCAL FracProduct, FracCounter, IntProdStr, FracOutStr, IntOutString
- LOCAL IntStr, FracString, FracLimit, Block, LChr, Remainder, Quotient
- LOCAL NegSign
-
- cInString := UPPER( ALLTRIM( cInString ) )
-
- #ifndef NOARGCHECK
- // Check parameters
- IF EMPTY( cInString ) .OR. VALTYPE( cInString ) <> "C" .OR. LEN( cInString ) > 19
- cNewBaseValue := NIL
- ELSE
- nInBase := IF( EMPTY( nInBase ), 10, nInBase )
- nOutBase := IF( EMPTY( nOutBase ), 10, nOutBase )
- IF VALTYPE( nInBase ) <> "N" .OR. VALTYPE( nOutBase ) <> "N"
- cNewBaseValue := NIL
- ELSE
- // Check out-of-range bases
- IF ( nInBase > 36 .OR. nOutBase > 36 .OR. nInBase < 2 .OR. nOutBase < 2 )
- cNewBaseValue := NIL
- ELSE
- i := 1
- DO WHILE i++ < LEN( cInString ) .AND. cNewBaseValue <> NIL
- IF .NOT. SUBSTR( cInString, i, 1 ) $ ( SUBSTR( DIGITS, 1, nInBase ) + "." )
- cNewBaseValue := NIL
- ENDIF
- ENDDO
- ENDIF
- ENDIF
- ENDIF
- #endif
-
- IF cNewBaseValue <> NIL
-
- // Check if cInString is negative
- NegSign := IF( SUBSTR( cInString, 1, 1 ) == "-", "-", "" )
- IF .NOT. EMPTY( NegSign )
- cInString := SUBSTR( ALLTRIM( SUBSTR( cInString, 2 ) ), 2 )
- ENDIF
-
- // Locate the decimal
- DecPos := AT( ".", cInString )
- IntStr := IF( DecPos > 1, SUBSTR( cInString, 1, DecPos - 1 ), IF( DecPos == 1, "0", cInString ) )
- FracString := IF( DecPos > 0, SUBSTR( cInString, DecPos + 1 ), "0" )
-
- // Convert integer portion to base 10
- FOR i = LEN( IntStr ) TO 1 STEP -1
- IntValue += ( AT( SUBSTR( IntStr, i, 1 ), DIGITS) - 1) * ( nInBase ** ( LEN( IntStr ) - i ) )
- NEXT
-
- // Convert fraction portion to base 10
- FOR i := 1 TO LEN( FracString )
- FracValue += ( AT( SUBSTR( FracString, i, 1 ), DIGITS ) - 1 ) * ( nInBase ** ( - i ) )
- NEXT
-
- // Calculate output string for integer portion
- Quotient := IntValue
- IntOutString := ""
-
- DO WHILE Quotient <> 0
- Remainder := Quotient % nOutBase
- Quotient := INT( Quotient / nOutBase )
- IntOutString := SUBSTR( Digits, Remainder + 1, 1 ) + IntOutString
- ENDDO
-
- IntOutString := IF( EMPTY( IntOutstring ), "0", IntOutString )
-
- // Calculate output string for fraction portion
- FracLimit := 19 - DecPos
- FracProduct := FracValue
- FracCounter := 1
- FracOutStr := ""
-
- // If the following WHILE condition is replaced with
- // FracCounter++ < FracLimit .AND. FracProduct < 0.00000000000001
- // then there is no need for execute the block to get rid of
- // trailing zeros.
-
- DO WHILE FracCounter++ < FracLimit .AND. FracProduct <> 0
- IntProdStr := FracProduct * nOutBase
- FracOutStr := FracOutStr + SUBSTR( Digits, INT( IntProdStr ) + 1, 1 )
- FracProduct := IntProdStr - INT( IntProdStr )
- ENDDO
-
- // Get rid of trailing zeros from the fraction portion
- Block:={ || LChr := RIGHT(FracOutStr, 1), ;
- IF(LChr == "0", FracOutStr := SUBSTR(FracOutStr, 1, LEN(FracOutStr) - 1), 0), ;
- IF(LChr == "0", EVAL(Block), FracOutStr) }
- FracOutStr := EVAL( Block )
-
- /* The following block takes more memory but is shorter
- Block := { |Str| IF(RIGHT(Str, 1) == "0", ;
- EVAL(Block, SUBSTR(FracOutStr, 1, LEN(FracOutStr) - 1)), Str)}
- */
- ENDIF
-
- // Output
- IF cNewBaseValue <> NIL
- cNewBaseValue := IF( DecPos > 0, NegSign + IntOutString + "." + FracOutStr, IntOutString )
- ENDIF
-
- RETURN cNewBaseValue
-
-
-
- /***
- * Ceiling( <nNumber> ) --> nInteger
- * Return the smallest integer that is greater than or equal to <nNumber>
- *
- */
- FUNCTION Ceiling( nNumber )
- LOCAL nInteger
-
- IF (INT(nNumber) = nNumber) .OR. (nNumber < 0)
- // Integers and negative non-integers
- nInteger := INT(nNumber)
-
- ELSEIF (nNumber > 0)
- // Positive non-integers
- nInteger := INT(nNumber + 1)
-
- ENDIF
-
- RETURN nInteger
-
-
-
- /***
- * Dtor( <nDegrees> ) --> nRadians
- * Convert an angle size specified in radians to degrees
- *
- */
- FUNCTION Dtor( nDegrees )
- RETURN ((nDegrees/180) * PI())
-
-
-
- /***
- * Floor( <nNumber> ) --> nInteger
- * Return the largest integer that is less than or equal to <nNumber>
- *
- */
- FUNCTION Floor( nNumber )
- LOCAL nInteger
-
- IF (INT(nNumber) = nNumber) .OR. (nNumber > 0)
- // Integers and positive non-integers
- nInteger := INT(nNumber)
-
- ELSEIF (nNumber < 0)
- // Negative non-integers
- nInteger := INT(nNumber - 1)
-
- ENDIF
-
- RETURN nInteger
-
-
-
- /***
- * NumAsCurrency( <nNumber>, <cSymbol>, <nSide> ) --> cCurrency
- * Convert number to currency format, floating dollar symbol
- *
- */
- FUNCTION NumAsCurrency( nNumber, cSymbol, nSide )
- LOCAL cCurrency
- // If nSide is negative, currency symbol goes on the left
- IF nSide < 0
- cCurrency := cSymbol + LTRIM(STR(nNumber))
- // Otherwise, currency symbol goes on the right
- ELSE
- cCurrency := RTRIM(STR(nNumber)) + cSymbol
- ENDIF
- RETURN cCurrency
-
-
-
- /***
- * NumAsLog10( <nNumber> ) --> nLog10
- * Convert a positive number to log base 10
- *
- */
- FUNCTION NumAsLog10( nNumber )
- IF nNumber > 0
- RETURN LOG(nNumber)/LOG(10)
- ENDIF
-
- RETURN NIL
-
-
-
- /***
- * NumGetDecimals( <nNumber> ) --> nDecimals
- * Determine the number of decimal digits
- *
- */
- FUNCTION NumGetDecimals( nNumber )
- LOCAL cNum, nPos
- cNum := STR(nNumber)
- nPos := AT(".", cNum)
- IF nPos > 0
- RETURN(LEN(ALLTRIM(SUBSTR(cNum, nPos + 1))))
- ENDIF
-
- RETURN 0
-
-
-
- /***
- * NumGetLen( <nNumber> ) --> nDigits
- * Determine the number of whole number digits
- *
- */
- FUNCTION NumGetLen( nNumber )
- LOCAL cNum
- cNum := STR(INT(ABS(nNumber)))
- RETURN(LEN(ALLTRIM(cNum)))
-
-
-
- /***
- * PI() --> nPI
- * Approximates the constant pi
- *
- */
- FUNCTION PI()
- RETURN (3.1415926535897932384626433)
-
-
-
- /***
- * Rtod( <nRadians> ) --> nDegrees
- * Convert an angle size specified in radians to degrees
- *
- */
- FUNCTION Rtod( nRadians )
- RETURN (180 * (nRadians/PI()))
-
-
-
- /***
- * Sign( <nNumber> ) --> nSign
- * Return the sign of a number
- *
- */
- FUNCTION Sign( nNumber)
- LOCAL nSign
- DO CASE
- CASE nNumber = 0
- nSign := 0
- CASE nNumber > 0
- nSign := 1
- CASE nNumber < 0
- nSign := -1
- ENDCASE
- RETURN nSign
-