472,951 Members | 1,756 Online

# floating point to ASCII conversion

Hello,

I want to efficient convert floating point numbers (IEEE754) into a
string. I have no library routines that do the job (like sprintf etc.),
because I work in an embedded environment.

My actual algorithm uses multiplying with 10 to shift the fraction into
an integer value and to aquire the used exponent. But the drawback is
obvious: When I have very small numbers like 3.141E-300 I have to make
300 time consuming floating point multiplies to convert this number.

But, since I know the IEEE754 structure and have directly access to the
exponent (of base 2) of a fp number, is there a faster method to convert
fp numbers to ASCII?

Regards

Peter
May 24 '07 #1
14 7896 Peter Sprenger wrote:
Hello,

I want to efficient convert floating point numbers (IEEE754) into a
string. I have no library routines that do the job (like sprintf etc.),
because I work in an embedded environment.

My actual algorithm uses multiplying with 10 to shift the fraction into
an integer value and to aquire the used exponent. But the drawback is
obvious: When I have very small numbers like 3.141E-300 I have to make
300 time consuming floating point multiplies to convert this number.

But, since I know the IEEE754 structure and have directly access to the
exponent (of base 2) of a fp number, is there a faster method to convert
fp numbers to ASCII?
If you have the frexp() function available, that might
make a good starting point.

--
Eric Sosman
es*****@acm-dot-org.invalid
May 24 '07 #2
Eric Sosman wrote:
Peter Sprenger wrote:
>Hello,

I want to efficient convert floating point numbers (IEEE754) into a
string. I have no library routines that do the job (like sprintf
etc.), because I work in an embedded environment.

My actual algorithm uses multiplying with 10 to shift the fraction
into an integer value and to aquire the used exponent. But the
drawback is obvious: When I have very small numbers like 3.141E-300 I
have to make 300 time consuming floating point multiplies to convert
this number.

But, since I know the IEEE754 structure and have directly access to
the exponent (of base 2) of a fp number, is there a faster method to
convert fp numbers to ASCII?

If you have the frexp() function available, that might
make a good starting point.
Nope, no frexp() available either.
May 24 '07 #3
Peter Sprenger wrote:
Eric Sosman wrote:
>Peter Sprenger wrote:
>>Hello,

I want to efficient convert floating point numbers (IEEE754) into a
string. I have no library routines that do the job (like sprintf
etc.), because I work in an embedded environment.

My actual algorithm uses multiplying with 10 to shift the fraction
into an integer value and to aquire the used exponent. But the
drawback is obvious: When I have very small numbers like 3.141E-300 I
have to make 300 time consuming floating point multiplies to convert
this number.

But, since I know the IEEE754 structure and have directly access to
the exponent (of base 2) of a fp number, is there a faster method to
convert fp numbers to ASCII?

If you have the frexp() function available, that might
make a good starting point.

Nope, no frexp() available either.
I'd suggest writing your own frexp() work-alike, using
your knowledge of the floating-point representation. The
you'll easily be able to move the code to other platforms;
something like a float-to-string-without-sprintf operation
seems of sufficiently wide applicability that you may well
want it again. So: invest a little non-portable work to get
yourself up to the frexp()-ish baseline, and write portable C
from there upwards.

Good luck!

--
Eric Sosman
es*****@acm-dot-org.invalid

May 24 '07 #4
>
I'd suggest writing your own frexp() work-alike, using
your knowledge of the floating-point representation. The
you'll easily be able to move the code to other platforms;
something like a float-to-string-without-sprintf operation
seems of sufficiently wide applicability that you may well
want it again. So: invest a little non-portable work to get
yourself up to the frexp()-ish baseline, and write portable C
from there upwards.

Good luck!
I was a little bit quick. In fact I can write a frexp() myself, that
separates exponent and mantissa. But then? I have a mantissa and an
exponent of base 2. I have no right idea to transform it from here to
an ascii string.

Regards

Peter
May 24 '07 #5
On Thu, 24 May 2007 14:44:39 +0200, Peter Sprenger wrote:
Hello,

I want to efficient convert floating point numbers (IEEE754) into a
string. I have no library routines that do the job (like sprintf etc.),
because I work in an embedded environment.

My actual algorithm uses multiplying with 10 to shift the fraction into
an integer value and to aquire the used exponent. But the drawback is
obvious: When I have very small numbers like 3.141E-300 I have to make
300 time consuming floating point multiplies to convert this number.

But, since I know the IEEE754 structure and have directly access to the
exponent (of base 2) of a fp number, is there a faster method to convert
fp numbers to ASCII?

Regards

Peter
If you have log, pow and floor then given a positive x

double log10 = log(x)/log(10.0);
int f = floor( log10);
double y = x*pow( 10.0, -f);

gets you y with 1<=y<10 and x = y * pow(10,f);

Duncan

May 24 '07 #6
On Thu, 24 May 2007 16:46:06 +0200, Peter Sprenger wrote:
>>
I'd suggest writing your own frexp() work-alike, using
your knowledge of the floating-point representation. The
you'll easily be able to move the code to other platforms;
something like a float-to-string-without-sprintf operation
seems of sufficiently wide applicability that you may well
want it again. So: invest a little non-portable work to get
yourself up to the frexp()-ish baseline, and write portable C
from there upwards.

Good luck!

I was a little bit quick. In fact I can write a frexp() myself, that
separates exponent and mantissa. But then? I have a mantissa and an
exponent of base 2. I have no right idea to transform it from here to
an ascii string.

Regards

Peter
If x is positive
int expon;
double frac = frexp(x, &expon);
int f = floor( expon*log_10_2);
double y = x*pow( 10.0, -f);
gets you y with 1<=y<10 and x = y*pow(10,f)
here log_10_2 is log base 10 of 2, ie around 0.301029995663981143

You can get the digits of f by eg iterating
d = (int)y; y = 10.0*(y-d);
Note that you're only doing this for the number of digits required.

If you don't have pow (and maybe even if you do) it can be written
fairly easily & efficiently since its second argument is an integer.
Duncan

May 24 '07 #7
On Thu, 24 May 2007 16:57:28 +0100, Duncan Muirhead wrote:
On Thu, 24 May 2007 16:46:06 +0200, Peter Sprenger wrote:
>>>
I'd suggest writing your own frexp() work-alike, using
your knowledge of the floating-point representation. The
you'll easily be able to move the code to other platforms;
something like a float-to-string-without-sprintf operation
seems of sufficiently wide applicability that you may well
want it again. So: invest a little non-portable work to get
yourself up to the frexp()-ish baseline, and write portable C
from there upwards.

Good luck!

I was a little bit quick. In fact I can write a frexp() myself, that
separates exponent and mantissa. But then? I have a mantissa and an
exponent of base 2. I have no right idea to transform it from here to
an ascii string.

Regards

Peter
If x is positive
int expon;
double frac = frexp(x, &expon);
int f = floor( expon*log_10_2);
double y = x*pow( 10.0, -f);
gets you y with 1<=y<10 and x = y*pow(10,f)
here log_10_2 is log base 10 of 2, ie around 0.301029995663981143

You can get the digits of f by eg iterating
d = (int)y; y = 10.0*(y-d);
Note that you're only doing this for the number of digits required.

If you don't have pow (and maybe even if you do) it can be written
fairly easily & efficiently since its second argument is an integer.
Duncan
Oops! Sorry, that's not quite right. In fact f above could be one
too small, and so we could have 10<=y<=100. I think the easiest thing
too do is to check for y being at least10, and if so fix it up.
Duncan

May 24 '07 #8
Peter Sprenger wrote On 05/24/07 10:46,:
> I'd suggest writing your own frexp() work-alike, using
your knowledge of the floating-point representation. The
you'll easily be able to move the code to other platforms;
something like a float-to-string-without-sprintf operation
seems of sufficiently wide applicability that you may well
want it again. So: invest a little non-portable work to get
yourself up to the frexp()-ish baseline, and write portable C
from there upwards.

Good luck!

I was a little bit quick. In fact I can write a frexp() myself, that
separates exponent and mantissa. But then? I have a mantissa and an
exponent of base 2. I have no right idea to transform it from here to
an ascii string.
You wrote originally about the time eaten up by the
very many multiplications by ten needed to scale a value
like 3.141E-300 to a reasonable range. I'm suggesting
that you use the exponent of two to figure out how many
"decades" of scaling you need, and do them all in one
multiplication. You could use a precomputed array with
the exponents as indices, or multiply the two's exponent
by log10(2) and do a little rounding and/or truncating
to get the ten's exponent.

x = m * 2**e
= m * (10**log10(2))**e
= m * 10**(log10(2)*e)
= m * 10**f
= m * 10**floor(f) * 10**(f - floor(f))
= (m * 10**(f - floor(f))) * 10**floor(f)

--
Er*********@sun.com
May 24 '07 #9
>
You wrote originally about the time eaten up by the
very many multiplications by ten needed to scale a value
like 3.141E-300 to a reasonable range. I'm suggesting
that you use the exponent of two to figure out how many
"decades" of scaling you need, and do them all in one
multiplication. You could use a precomputed array with
the exponents as indices, or multiply the two's exponent
by log10(2) and do a little rounding and/or truncating
to get the ten's exponent.

x = m * 2**e
= m * (10**log10(2))**e
= m * 10**(log10(2)*e)
= m * 10**f
= m * 10**floor(f) * 10**(f - floor(f))
= (m * 10**(f - floor(f))) * 10**floor(f)
Hello Eric,

you are right,

x = m * 2**e

is correct. But if I have use log10 in some way, isn't it easier to
directly get the exponent with directly log10(f) ? (f is my fp number)
And then multiply f to get it in the range 1.0 <= f < 10.0 ?

Your solution will not bring the answer on how many decimal places in
the fraction f has. So I have to multiply it anyway in turns to get the
decimal places after the comma.

Peter
May 25 '07 #10
>>Peter
If x is positive
int expon;
double frac = frexp(x, &expon);
int f = floor( expon*log_10_2);
double y = x*pow( 10.0, -f);
gets you y with 1<=y<10 and x = y*pow(10,f)
here log_10_2 is log base 10 of 2, ie around 0.301029995663981143

You can get the digits of f by eg iterating
d = (int)y; y = 10.0*(y-d);
Note that you're only doing this for the number of digits required.

If you don't have pow (and maybe even if you do) it can be written
fairly easily & efficiently since its second argument is an integer.
Duncan

Oops! Sorry, that's not quite right. In fact f above could be one
too small, and so we could have 10<=y<=100. I think the easiest thing
too do is to check for y being at least10, and if so fix it up.
Duncan
Hello Duncan,

you know the IEEE754 floating point format? The exponent says, where in
the mantissa the decimal point is (or should I say the binary point :-)
) and the fraction part begins.

Your terms don't use the mantissa, so I think they are not correct. But
like I wrote to Eric, if I can make a log10(x), I can bring x into
1<= x < 10 with one multiplication.

Peter
May 25 '07 #11
On Fri, 25 May 2007 09:28:13 +0200, Peter Sprenger wrote:
>
>>>Peter
If x is positive
int expon;
double frac = frexp(x, &expon);
int f = floor( expon*log_10_2);
double y = x*pow( 10.0, -f);
gets you y with 1<=y<10 and x = y*pow(10,f)
here log_10_2 is log base 10 of 2, ie around 0.301029995663981143

You can get the digits of f by eg iterating
d = (int)y; y = 10.0*(y-d);
Note that you're only doing this for the number of digits required.

If you don't have pow (and maybe even if you do) it can be written
fairly easily & efficiently since its second argument is an integer.
Duncan

Oops! Sorry, that's not quite right. In fact f above could be one
too small, and so we could have 10<=y<=100. I think the easiest thing
too do is to check for y being at least10, and if so fix it up.
Duncan

Hello Duncan,

you know the IEEE754 floating point format? The exponent says, where in
the mantissa the decimal point is (or should I say the binary point :-)
) and the fraction part begins.

Your terms don't use the mantissa, so I think they are not correct. But
like I wrote to Eric, if I can make a log10(x), I can bring x into
1<= x < 10 with one multiplication.

Peter
Indeed, you want a log10 and a pow. However all you really need is the
largest integer less than log10(x). Above I was musing about how you could
do that if you had frexp.
The point is that if
y = frexp( x, &p)
then we have x = pow(2,p)*y and 0.5<=y<=1
Taking logs (base 10) of this
log10(x) = p*log10(2) + log10(y)
but -log10(2)<=log10(y) <= 0
so the largest integer less than log10(x) is either the largest integer
less than p*log10(2), or one less than this, You can figure out which
by computing f = floor( p*log10) and then computing y = x*pow(10,-p).
if 1<=y<10 we're done; otherwise (ie 0.1<=y<10) multiply y by 0.1
and increase p by one.
Duncan

May 25 '07 #12
Peter Sprenger wrote:
>>
You wrote originally about the time eaten up by the
very many multiplications by ten needed to scale a value
like 3.141E-300 to a reasonable range. I'm suggesting
that you use the exponent of two to figure out how many
"decades" of scaling you need, and do them all in one
multiplication. You could use a precomputed array with
the exponents as indices, or multiply the two's exponent
by log10(2) and do a little rounding and/or truncating
to get the ten's exponent.

x = m * 2**e
= m * (10**log10(2))**e
= m * 10**(log10(2)*e)
= m * 10**f
= m * 10**floor(f) * 10**(f - floor(f))
= (m * 10**(f - floor(f))) * 10**floor(f)

Hello Eric,

you are right,

x = m * 2**e

is correct. But if I have use log10 in some way, isn't it easier to
directly get the exponent with directly log10(f) ? (f is my fp number)
And then multiply f to get it in the range 1.0 <= f < 10.0 ?
You only need an approximation to log10(f) to determine
the initial scaling amount. You can get that by extracting
the binary exponent (which is close to lg(f)) and multiplying
by the precomputed constant log10(2), then truncating or
rounding to a nearby integer.
Your solution will not bring the answer on how many decimal places in
the fraction f has. So I have to multiply it anyway in turns to get the
decimal places after the comma.
Yes, but you avoid the nearly three hundred multiplications
by ten that work through the leading zeroes of 3.141E-300.
If you get to 0.1 <= abs(f)*scale < 1 in one step, you only
need as many additional multiplications as you want digits.[*]
[*] Optimization: multiply by 1E8 instead of by 10, and
work on groups of eight digits at a time in `long' instead
of one digit at a time in floating-point.

--
Eric Sosman
es*****@acm-dot-org.invalid
May 25 '07 #13
Eric Sosman wrote:
Peter Sprenger wrote: *** and deleted attributions ***
>>>
You wrote originally about the time eaten up by the very many
multiplications by ten needed to scale a value like 3.141E-300
.... snip ...
>>
is correct. But if I have use log10 in some way, isn't it easier
to directly get the exponent with directly log10(f) ? (f is my fp
number) And then multiply f to get it in the range 1.0 <= f < 10.0 ?
.... snip ...
>[*] Optimization: multiply by 1E8 instead of by 10, and work on
groups of eight digits at a time in `long' instead of one digit
at a time in floating-point.
To maintain accuracy, that 1E8 should be some value that is
expressed exactly in the FP system in use, and as large as
possible. For division, use the same value, and not it's inverse
(which will not be exact in most systems).

--
<http://www.cs.auckland.ac.nz/~pgut001/pubs/vista_cost.txt>
<http://www.securityfocus.com/columnists/423>
<http://www.aaxnet.com/editor/edit043.html>
cbfalconer at maineline dot net

--
Posted via a free Usenet account from http://www.teranews.com

May 25 '07 #14
Peter Sprenger wrote:
>>If x is positive
int expon;
double frac = frexp(x, &expon);
int f = floor( expon*log_10_2);
double y = x*pow( 10.0, -f);
gets you y with 1<=y<10 and x = y*pow(10,f)
here log_10_2 is log base 10 of 2, ie around 0.301029995663981143

You can get the digits of f by eg iterating
d = (int)y; y = 10.0*(y-d);
Note that you're only doing this for the number of digits required.

If you don't have pow (and maybe even if you do) it can be written
fairly easily & efficiently since its second argument is an integer.
Duncan

Oops! Sorry, that's not quite right. In fact f above could be one
too small, and so we could have 10<=y<=100. I think the easiest thing
too do is to check for y being at least10, and if so fix it up.

you know the IEEE754 floating point format? The exponent says, where in
the mantissa the decimal point is (or should I say the binary point :-)
) and the fraction part begins.

Your terms don't use the mantissa, so I think they are not correct. But
like I wrote to Eric, if I can make a log10(x), I can bring x into
1<= x < 10 with one multiplication.
Peter,

Duncan has a good approach. It uses an frexp(), which you can write, a
floating multiplication and conversion to integer, then the pow()
function, which can be implemented with some combination of table
lookups and multiplication. And, as Duncan noted later, you may need to
do a final adjustment on the power of 10.

In general, the larger the lookup table, the fewer multiplications that
are needed. For example, there are 81 different powers of 10 from 1e-40
to 1e+40. You can use a table of powers of 1e9 from 1e-36 to 1e+36,
then powers of 10 from 1e-4 to 1e8. With 22 entries and one
multiplication you get any power of 10 from 1e-40 to 1e+40. Or you can
use a table with 81 entries and no multiplication. There are other
feasible combinations, as well.

--
 4 by: Roger Leigh | last post by: Hello, I'm writing a fixed-precision floating point class, based on the ideas in the example fixed_pt class in the "Practical C++ Programming" book by Steve Oualline (O' Reilly). This uses a... 31 by: JS | last post by: We have the same floating point intensive C++ program that runs on Windows on Intel chip and on Sun Solaris on SPARC chips. The program reads the exactly the same input files on the two platforms.... 16 by: BigMan | last post by: How can I check if assignment of a float to a double (or vice versa) will result in loss of precision? 10 by: 63q2o4i02 | last post by: Hi, I'm using python to run some lab equipment using PyVisa. When I read a list of values from the equipment, one of the fields is 32 bits of flags, but the value is returned as a floating... 4 by: riya1012 | last post by: hello guys, I need some help from you. I am doing a DSP project and for that I need to do some C coding for the conversion of sample data which is in floating point representation to fixed point... 70 by: Robert Gamble | last post by: 9899:1999 5.1.2.3 Example 4 reads: "EXAMPLE 4 Implementations employing wide registers have to take care to honor appropriate semantics. Values are independent of whether they are represented in a... 39 by: rembremading | last post by: Hi all! The following piece of code has (for me) completely unexpected behaviour. (I compile it with gcc-Version 4.0.3) Something goes wrong with the integer to float conversion. Maybe somebody... 15 by: arnuld | last post by: Next month I will start to work on a C++ based Software named CAT++ which is going to provide FORTRAN like arrays in C++ and will be used within Scientific Community and hence will heavily depend... 7 by: ma740988 | last post by: Consider the equation (flight dynamics stuff): Yaw (Degrees) = Azimuth Angle(Radians) * 180 (Degrees) / 3.1415926535897932384626433832795 (Radians) There's a valid reason to use single... 0 by: Mushico | last post by: How to calculate date of retirement from date of birth 2 by: DJRhino | last post by: Was curious if anyone else was having this same issue or not.... I was just Up/Down graded to windows 11 and now my access combo boxes are not acting right. With win 10 I could start typing... 0 by: tracyyun | last post by: Hello everyone, I have a question and would like some advice on network connectivity. I have one computer connected to my router via WiFi, but I have two other computers that I want to be able to... 2 by: giovanniandrean | last post by: The energy model is structured as follows and uses excel sheets to give input data: 1-Utility.py contains all the functions needed to calculate the variables and other minor things (mentions... 4 by: NeoPa | last post by: Hello everyone. I find myself stuck trying to find the VBA way to get Access to create a PDF of the currently-selected (and open) object (Form or Report). I know it can be done by selecting :... 3 by: NeoPa | last post by: Introduction For this article I'll be using a very simple database which has Form (clsForm) & Report (clsReport) classes that simply handle making the calling Form invisible until the Form, or all... 3 by: nia12 | last post by: Hi there, I am very new to Access so apologies if any of this is obvious/not clear. I am creating a data collection tool for health care employees to complete. It consists of a number of... 0 by: NeoPa | last post by: Introduction For this article I'll be focusing on the Report (clsReport) class. This simply handles making the calling Form invisible until all of the Reports opened by it have been closed, when it... 0 by: isladogs | last post by: The next online meeting of the Access Europe User Group will be on Wednesday 6 Dec 2023 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, Mike...