Normazile float numbers

How can I Normalize two float numbers


Suppose the input of users as this

1.98 x 10E 4   = 19800
 21.22 x 10E5 = 2120000

But I need to set them as

0.19 x 10 E -5
and the second one must be 0 in the first digit and must be the same exponent
0.2122 x 10E-6 -> as this is greater than first I must move the coma of the first one

0.019 x 10 E -6
0.2122 x 10 E -6

I need to make this in a single function.
LVL 10
djhexAsked:
Who is Participating?
 
itsmeandnobodyelseCommented:
Actually, your samples are not very accurate:

- you are rounding 1.98 x 10E4 to  0.19 x 10E5 . Where is the 8 ???
- 1.98 x 10E4  = 0.198 E5  *and not* 0.198 E-5
- 21.22 x 10 E5 = 0.2122 E7 *and not* 0.2122 E-6 ???
- you are stating that 0.19 E-5 is less than 0.2122 E-6 what definitively is false
- 0.2122 E7 is greater 0.198 E5  (that is what you most likely mean)
- to show both numbers in the same dimension you would need to show the first as 0.00198 E7

>>>> How can I Normalize two float numbers

Actually, float numbers are already normalized. The internal representation of a float f is

     f = n * (2 ^ e)

where     1 <  abs(n) <= 2   (n is called mantissa)  and e is an integer called 'exponent'

Your sample shows that you want normalize the gerater number of a pair of floats  to 'decimal' form where the base of the exponent is 10 and the mantissa is between 0.1 and 1.0. After that you want the smaller number to have the same decimal exponent.

It is not clear whether the result should be floats or strings. Note, if you want floats, the results are 'rounded' as the internal representation of a float is a 'binary' representation (see above) that does not exactly match to a decimal representation for almost all numbers. The normalize function of Dariusz would do the job though it can't handle negative numbers and numbers less than 0.1

void swap(float& f1, float& f2)
{
     float f = f1; f1 = f2; f2 = f;
}

int normalizeTwoFloats( float f1, float f2, float& r1, float& r2 )
{
    bool neg1  = (f1 < 0.);
    bool neg2  = (f2 < 0.);
    r1 = (neg1)? -f1 : f1;
    r2 = (neg2)? -f2 : f2;
    bool toggle = (r1 < r2);
    if (toggle) swap(r1, r2);
   
    float  df = (r1 <= 0.1)? 10 : 0.1;
    int     st = (r1 <= 0.1)? -1 : 1;
    int     e  = 0;
    while (r1 <= 0.1 || 1. < r1)
    {
        r1 *= df;
        r2 *= df;
        e += st;
    }
    if (toggle) swap(r1, r2);
    if (neg1) r1 = -r1;
    if (neg2) r2 = -r2;
    return e;
}

That can be used like that:

#include <iostream>
#include <iomanip>
using namespace std;

int main()
{  
    float r1, r2;
    int dim = normalizeTwoFloats(float(1.98E4), float(21.22E5), r1, r2);
   
    cout << setiosflags(ios::fixed) << r1 << "E" << dim << "\t"
           << setiosflags(ios::fixed) << r2 << "E" << dim << endl;
   
    return 0;
}


If you only need normalized string output you could do that:

string normalizedString(float f, int& dim, bool calcDim = true)
{
      const int precision = 8;   // 8 digits required
      int e;
      int sig;
      char* psz = ecvt(f, precision, &e, &sig);
      string s;
      char buf[10];
      for (int i = strlen(psz)-1; i >=  0; --i)
           if (psz[i] == '0') psz[i] = '\0';
      if (sig)  s += '-';
      s += "0.";
      if  (calcDim ||  dim < e)
      {
             s += psz;
             dim = e;
      }
      else
      {
           for (int j = e; j < dim; ++j)
               s += '0';
           s += psz;  
      }
      s += "E";
      s += itoa(dim, buf, 10);
      return s;
}

int main()
{
    float f1 = 1.98E4;
    float f2 = 21.22E5;
    float r1 = f1;
    float r2 = f2;
    if (f1 < f2) swap(r1, r2);
    string s1 = normalizedString(r1, dim);
    string s2 = normalizedString(r2, dim, false);
    if (f1 < f2) swap(s1, s2);
    cout << s1 << "\t" << s2 << endl;
    return 0;
}

Regards, Alex

     

   

 
0
 
venkateshwarrCommented:
Is this what u wanted??

double getNormalValue(double dnum)
{
     while(dnum>1)
          dnum /= 10;
     printf("num = %E",dnum);
     return dnum;
}
0
 
DariuzkCommented:
Hi,

I think venkateshwarr wrote part of
solution, but you need to chek which
of numers is bigger and then normalize
numbers.

#include <iostream>

using namespace std;

int main(){

      double num1 = 0, num2 = 0;

      cout << "Input two numbers" << endl;
      cin >> num1 >> num2;
      
      if (num1 >= num2)
      {
            while(num1 > 1)
            {
                  num1 /= 10;
                  num2 /= 10;
            }
                  
      }
      else
      {
            while(num2 > 1)
            {
                  num1 /= 10;
                  num2 /= 10;
            }
      }

      cout << "num1 = "  << num1
           << " num2 = " << num2
           << endl;
}
0
Cloud Class® Course: CompTIA Cloud+

The CompTIA Cloud+ Basic training course will teach you about cloud concepts and models, data storage, networking, and network infrastructure.

 
DariuzkCommented:
void normalize(double &num1, double &num2)
   
     if (num1 >= num2)
     {
          while(num1 > 1)
          {
               num1 /= 10;
               num2 /= 10;
          }
               
     }
     else
     {
          while(num2 > 1)
          {
               num1 /= 10;
               num2 /= 10;
          }
     }

}
0
 
grg99Commented:
The above examples only handle one of four cases, when the numbers are larger than desired, and positive.
The code below works when the numbers are either too big or too small, and for negative values also:



          while( abs(num1) < 1.0 && abs(num2) < 1.0 )    {  num1 *= 10.0;    num2 *= 10.0;  }

          while( abs(num1) > 1.0 && abs(num2) > 1.0 )    {  num1 /= 10.0;     num2 /= 10.0;   }

0
 
djhexAuthor Commented:
I have to test it when I go home tonight. Thanks For the help.

Does this work on C too? What I need to change?
0
 
grg99Commented:
OOPS, never mind!      All the examples above are scaling the numbers, but you apparently just want to display both of them with the same exponent, and the larger one between 0 and 1.   Try this instead:

double Larger;   int Exponent;

if( abs(num1) > abs(num2) ) Larger = num1; else Larger = num2;

Exponent  = 0;


while( abs( Larger ) < 1.0 ) { Larger *= 10.0;  num1 *= 10.0; num2 *= 10.0; Exponent--; }

while( abs( Larger ) >= 1.0 ) { Larger /= 10.0;  num1 /= 10.0; num2 /= 10.0;  Exponent++; }

printf( "num1 = %10.5f  x 10^%d  num2 = %10.5f x 10^%d\n", num1, Exponent, num2, Exponent );

0
 
djhexAuthor Commented:
I need to normalize to the same exponent because the internal representation of float is in IEEE Format. and I need to sum 2 float numbers in assembly language. SO its better that I send the assembler function the numbers already normalized  so the BITS of the exponent will be the same and I can sum the bits of the mantissa easily without having to program a normalization in assembly.
0
 
djhexAuthor Commented:
I was making some test in this but I think It Will not Work.

http://babbage.cs.qc.edu/courses/cs341/IEEE-754.html

Put
0.101

and 0.0101

The exponent bits are different but as you see THIS HAS THE SAME EXPONENT:


I think I am confused.

What I just want is that binary representation of the exponents bits are the same on both numbers so I can make a binary addition in assembler of the mantisas.

0
 
grg99Commented:
Your're confusing the base 10 printout of the numbers with the base2 representation.

In memory floating-point numbers are kept in a binary normalized format with a binary exponent.  

So when you execute the statement   X = 12345.678 E 5, the compiler at compile time  first converts that string of decimal digits to the correct IEEE format, normalized, then generates the code to do the assignment.

So by the time your program is running, all the IEEE format numbers are already normalized.

Also when you go to add two floating-point numbers, the ADD or SUB instructions align the mantissas as needed-- you never have to do this yourself.

Unless your goal is to SIMULATE the addition with a series of instructions, instead of using the built-in FPU ADD instruction.

Hope this clears things up a bit.


0
 
djhexAuthor Commented:
My goal is to SIMULATE without using FPU. Any suggestions please.
0
 
djhexAuthor Commented:
If you know how to  make the addition I will give you more points if Needed.
0
 
grg99Commented:
You could get some ideas by looking at the various floating-point emulation libraries.  

The old PC's didnt all have FPU's, so compilers came with emulation libraries, that emulated the floating-point operations (to various levels of completeness).  

You could compile a little test program that does x = a + b, using the "NOFPU" option on your compiler., then step thru it to see how it does it.

Or download the gcc or watcom C library source code and look at their floating point emulation stuff.

Just to get the rough idea, pls don't copy the code verbatim (or even dysan).
0
 
djhexAuthor Commented:
Can I make that with any Ide??
I have and Ide called  DevC++ of bloodshed.? DOes it make that?

0
 
djhexAuthor Commented:
Does it convert my function to assembler? Which file does it generate to the the assembly code?
0
 
grg99Commented:
I don't know aboput bloodshed, to see the FPU emulation code you'll need a debugger that can step into the asm code.

You're probably better off downloading the source of a FPU emulator, such as the one in gcc or Watcom C.

0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.