?
Solved

Normazile float numbers

Posted on 2005-04-13
17
Medium Priority
?
305 Views
Last Modified: 2012-05-05
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.
0
Comment
Question by:djhex
  • 7
  • 5
  • 2
  • +2
16 Comments
 
LVL 12

Expert Comment

by:venkateshwarr
ID: 13779099
Is this what u wanted??

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

Expert Comment

by:Dariuzk
ID: 13779371
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
 
LVL 2

Expert Comment

by:Dariuzk
ID: 13779837
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
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 
LVL 22

Expert Comment

by:grg99
ID: 13781545
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
 
LVL 10

Author Comment

by:djhex
ID: 13781592
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
 
LVL 22

Expert Comment

by:grg99
ID: 13781637
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
 
LVL 39

Accepted Solution

by:
itsmeandnobodyelse earned 1000 total points
ID: 13783515
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
 
LVL 10

Author Comment

by:djhex
ID: 13784094
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
 
LVL 10

Author Comment

by:djhex
ID: 13784155
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
 
LVL 22

Expert Comment

by:grg99
ID: 13784209
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
 
LVL 10

Author Comment

by:djhex
ID: 13784234
My goal is to SIMULATE without using FPU. Any suggestions please.
0
 
LVL 10

Author Comment

by:djhex
ID: 13784258
If you know how to  make the addition I will give you more points if Needed.
0
 
LVL 22

Expert Comment

by:grg99
ID: 13784443
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
 
LVL 10

Author Comment

by:djhex
ID: 13784464
Can I make that with any Ide??
I have and Ide called  DevC++ of bloodshed.? DOes it make that?

0
 
LVL 10

Author Comment

by:djhex
ID: 13784486
Does it convert my function to assembler? Which file does it generate to the the assembly code?
0
 
LVL 22

Expert Comment

by:grg99
ID: 13784881
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

Featured Post

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Unlike C#, C++ doesn't have native support for sealing classes (so they cannot be sub-classed). At the cost of a virtual base class pointer it is possible to implement a pseudo sealing mechanism The trick is to virtually inherit from a base class…
Article by: evilrix
Looking for a way to avoid searching through large data sets for data that doesn't exist? A Bloom Filter might be what you need. This data structure is a probabilistic filter that allows you to avoid unnecessary searches when you know the data defin…
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.
Suggested Courses

621 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question