Solved

# Normazile float numbers

Posted on 2005-04-13
291 Views
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
Question by:djhex

LVL 12

Expert Comment

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

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

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

LVL 22

Expert Comment

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

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

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

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

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

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

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.

Hope this clears things up a bit.

0

LVL 10

Author Comment

My goal is to SIMULATE without using FPU. Any suggestions please.
0

LVL 10

Author Comment

If you know how to  make the addition I will give you more points if Needed.
0

LVL 22

Expert Comment

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

Can I make that with any Ide??
I have and Ide called  DevC++ of bloodshed.? DOes it make that?

0

LVL 10

Author Comment

Does it convert my function to assembler? Which file does it generate to the the assembly code?
0

LVL 22

Expert Comment

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

### Suggested Solutions

Often, when implementing a feature, you won't know how certain events should be handled at the point where they occur and you'd rather defer to the user of your function or class. For example, a XML parser will extract a tag from the source code, whâ€¦
Container Orchestration platforms empower organizations to scale their apps at an exceptional rate. This is the reason numerous innovation-driven companies are moving apps to an appropriated datacenter wide platform that empowers them to scale at a â€¦
The goal of the tutorial is to teach the user how to use functions in C++. The video will cover how to define functions, how to call functions and how to create functions prototypes. Microsoft Visual C++ 2010 Express will be used as a text editor anâ€¦
The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relatâ€¦