At 12:47 PM 7/10/01 -0600, you wrote:
>This could actually be pretty trivial.  Based on your earlier questions,

Unfortunately, it's not - it only seems that way. I requested some sample 
code last month, but it wasn't useful to me because it didn't use the 
Fpl... functions. It assumed the existence of type float. The code I was 
writing had to work on a OS 1.0 device, so I wrote my own.

I've appended my code below. If anyone's interested in critiquing it, I'd 
appreciate the peer review.

* Hope the tabs turn out alright!

Jaba - http://www.shinyfish.com

//////////////////////////////////////////////////////////////////////
// Copyright 2001, Jabavu Adams ([EMAIL PROTECTED]).
//
// You may use the following code for any purpose. You must accept that
// it is distributed "AS IS" and WITHOUT ANY WARRANTY. You use it at
// your own risk. I am not responsible for any consequences of your
// use of (or failure to use) this software.
//
// So there! :P

#include <Pilot.h>
#include <FloatMgr.h>


//////////////////////////////////////////////////////////////////////
// FUNCTION PROTOTYPES - put these in a header file

char*           FormatFloat( FloatType fnum, UInt16 decimalChars );
FloatType       RoundFloat( FloatType fnum, int decimals );

//////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////
// Allocates a new string that the caller owns. Caller must de-
// allocate.

char*
FormatFloat(
         FloatType       fnum,           // The number to format.
         UInt16          decimals        // Number of decimal places to show.
)
{
         char* resultStr = 0;

         // Use FplFToA to get the number in scientific notation.
         // FplFToA returns a string in the following format:
         // "[-]x.yyyyyyyye[-]zz" [PalmOS 3.5 Reference]

         const UInt32 maxChars = 15;
         char sciStr[ maxChars + 1 ];
         MemSet( sciStr, maxChars+1, 0 );

         fnum = RoundFloat( fnum, decimals );
         Err err = FplFToA( fnum, sciStr );
         if ( err ) {
                 return 0;
         }

         // Next, get the exponent and sign, which we'll need in order
         // to calculate how much space to allocate for the result.

         ULong   mantissa;
         Int             exponent;
         Int             sign;

         err = FplBase10Info( fnum, &mantissa, &exponent, &sign );
         if ( err ) {
                 return 0;
         }

         // WARNING WARNING  PALMOS  BUG BUG
         // Don't trust the value of exponent returned by FplBase10Info. 
For example,
         // for "1", it returns an exponent of -7!!!
         // START BUGFIX

         char* expP = sciStr;
         while ( *expP != 0 && *expP != 'e') {
                 expP++;
         }
         if ( 0 == *expP ) {
                 exponent = 0;
         }
         else {
                 expP++;
                 exponent = StrAToI( expP );
         }

         // END BUGFIX

         // Fixup sign parameter. FplBase10Info reports "0" as having a
         // negative sign; we want "0" to be positive.

         if ( 0 == mantissa ) {
                 sign = 1;
         }

         // Okay, now we can calculate the size of string required to hold
         // the result.

         UInt16 allocSize = 2;   // enough space for one digit and null
         if ( -1 == sign ) {
                 allocSize++;            // add space for minus sign
         }
         if ( decimals > 0 ) {
                 allocSize += 1 + decimals;      // add space for . and 
decimals
         }
         if ( exponent > 0 && mantissa != 0) {
                 allocSize += exponent;  // add space for digits left of .
         }

         resultStr = (char*) MemPtrNew( allocSize );
         if ( resultStr ) {
                 MemSet( resultStr, allocSize, 0 );

                 char* dstP = resultStr; // write to this pointer
                 char* srcP = sciStr;            // read from this pointer

                 // Leading minus sign?

                 if ( -1 == sign ) {
                         *dstP++ = '-';
                         *srcP++;
                 }

                 // We want lastP to point to the last significant digit in the
                 // scientific-notation source. This is either the 
character before
                 // the 'e', or the first char if the string is "0".

                 char* lastP = srcP;
                 while ( *lastP != 0 && *lastP != 'e') {
                         lastP++;
                 }
                 lastP--;

                 // Now, the real conversion work ...

                 Int digits;
                 Boolean wroteDot = false;

                 // If the exponent is less than 0, we may need to pad the 
left
                 // with zeros.

                 if ( exponent < 0 ) {
                         *dstP++ = '0';
                         if ( decimals > 0 ) {
                                 *dstP++ = '.';
                                 wroteDot = true;
                         }

                         digits = decimals;
                         while (digits > 1 + decimals + exponent) {
                                 *dstP++ = '0';
                                 digits--;
                         }
                 }
                 else {
                         digits = 1 + exponent + decimals;
                 }

                 // Main loop - copy significant digits.

                 while ( digits && srcP <= lastP ) {
                         if ( '.' == *srcP ) {
                                 srcP++;
                                 continue;
                         }
                         else {
                                 if ( digits == decimals && !wroteDot ) {
                                         *dstP++ = '.';
                                         wroteDot = true;
                                         continue;
                                 }
                                 else {
                                         *dstP++ = *srcP++;
                                 }
                         }
                         digits--;
                 }

                 // Finally, for large numbers, we may need to pad to the right
                 // of the significant digits with zeros.

                 while ( digits ) {
                         if ( digits == decimals && !wroteDot ) {
                                 *dstP++ = '.';
                                 wroteDot = true;
                                 continue;
                         }
                         else {
                                 *dstP++ = '0';
                         }
                         digits--;
                 }
         }

         // TODO: Localize the number.
         return resultStr;
}


//////////////////////////////////////////////////////////////////////
FloatType RoundFloat( FloatType fnum, int decimals ) {
         FloatType bias                  = FplAToF( "0.5" );
         FloatType f10                   = FplLongToFloat( 10 );
         FloatType multiplier    = FplLongToFloat( 1 );

         // Validate parameters.

         if ( decimals < 0 ) {
                 return fnum;
         }

         // We'll round by biasing the number up, then truncating.
         // First, multiply to get all our significant digits.

         for (int i = 0; i < decimals; i++ ) {
                 multiplier = FplMul( multiplier, f10 );
         }
         fnum = FplMul( fnum, multiplier );

         // Need to know whether fnum is positive, or negative so that
         // we know whether to add or subtract the bias, respectively.

         ULong   mantissa;
         Int             exponent;
         Int             sign;

         FplBase10Info( fnum, &mantissa, &exponent, &sign );
         if ( 0 == mantissa ) {
                 return FplLongToFloat( 0 );
         }

         if ( 1 == sign ) {
                 // fnum is positive.
                 fnum = FplAdd( fnum, bias );
         }
         else if ( -1 == sign ){
                 // fnum is negative.
                 fnum = FplSub( fnum, bias );
         }

         // Now truncate.
         fnum = FplLongToFloat( FplFloatToLong( fnum ) );
         fnum = FplDiv( fnum, multiplier );

         return fnum;
}




-- 
For information on using the Palm Developer Forums, or to unsubscribe, please see 
http://www.palmos.com/dev/tech/support/forums/

Reply via email to