Precision Change - Float to String

B

Bryan R. Meyer

I am a relatively new C++ programmer and am attempting to write a
function that takes a number of type float and adds commas to it in
the appropriate places. In order to manipulate the number to add the
commas, I convert it to a string (specifically a char[] rather than an
actual string object) using the
gcvt function as shown below.

char amt[50];
gcvt(amount,50,amt);

The problem I run into is a change in the precision. If amount is of
type float and has a value of 264588.44 then the code above results in
the string amt being "264588.4375". Note the change in the decimal
portion of the number; I don't want this. I want the original number
in the string. People have suggested using sprintf(). However,
sprintf() won't help me since I don't know the number of decimal
places in advance of the conversion.

Is there any way around this? Keep in mind that I don't know how many
decimal places I will need.

Thanks,
Bryan
 
V

Victor Bazarov

Bryan R. Meyer said:
I am a relatively new C++ programmer and am attempting to write a
function that takes a number of type float and adds commas to it in
the appropriate places. In order to manipulate the number to add the
commas, I convert it to a string (specifically a char[] rather than an
actual string object) using the
gcvt function as shown below.

char amt[50];
gcvt(amount,50,amt);

The problem I run into is a change in the precision. If amount is of
type float and has a value of 264588.44 then the code above results in
the string amt being "264588.4375". Note the change in the decimal
portion of the number; I don't want this.

How do you know that it "has a value of 264588.44" unless you convert
it to a string (which you have) and read the result? And if such
conversion does not give you what you think it should give you, what
reason do you have to doubt it?
I want the original number
in the string.

What is "the original number"? How did it come into being? Why do
consider it "the original"? Is that a constant you wrote in the C++
source file? Do you know that many numbers cannot be represented
precisely in a double or a float? Take 0.1 for example. It cannot
be represented in a limited amount of binary digits. So, the real
number is not what you think it is, but it's kinda close. And when
time comes to convert it back into characters, some part of the
number is lost, in your case 0.0025. That's rounding and truncation
happening in memory when you store a double (or float) value in some
limited number of bits.
People have suggested using sprintf(). However,
sprintf() won't help me since I don't know the number of decimal
places in advance of the conversion.

Is there any way around this? Keep in mind that I don't know how many
decimal places I will need.

If you don't know how many you'll need, how do you know that what you're
getting is wrong?

V
 
B

Bryan R. Meyer

Victor Bazarov said:
What is "the original number"? How did it come into being? Why do
consider it "the original"? Is that a constant you wrote in the C++
source file? Do you know that many numbers cannot be represented
precisely in a double or a float?

I am very well aware that floating-point numbers cannot be represented
exactly. Simply for testing purposes, my "original number" is a
constant in my program. I wanted to convert the number 264588.44 from
a floating-point number to a string. I attempted to use the gcvt
function to do this and it returned a string with the vaue
"264588.4375". This is unacceptable in the context of my program.

My intention is to write a function that takes a parameter of type
float and adds commas to the number in the appropriate places. This
is achieved by first converting the float to a string. It does not
suit me that after conversion to a string that I will be adding commas
to a number that was different than the original passed into the
function. I was merely trying to determine if there was some sort of
workaround for this. I do not know all of the limitations of C++.
If you don't know how many you'll need, how do you know that what you're
getting is wrong?

The example I gave was just a constant. If I have a variable num of
type float with the value 35453.3466 then I don't want to add the
commas to a number that is different, say 35453.34656576. This holds
true for any floating-point number that may be passed into the
function.

I am just a newbie in C++. I do not know every single thing the
language can and cannot do for me. I was simply trying to get some
insight into a problem I was having and wanted some input.

Thanks,
Bryan
 
R

Rolf Magnus

Bryan said:
I am very well aware that floating-point numbers cannot be represented
exactly. Simply for testing purposes, my "original number" is a
constant in my program. I wanted to convert the number 264588.44 from
a floating-point number to a string. I attempted to use the gcvt
function to do this and it returned a string with the vaue
"264588.4375". This is unacceptable in the context of my program.

Maybe 264588.44 is one of those numbers that cannot be exactly
represented in a double.
My intention is to write a function that takes a parameter of type
float

A float or a double? Note that the precision of float is typically very
limited. On most systems, that precision is less than the 8 digits that
are required for 264588.44. There is most often no good reason to
prefer float over double anyway.
and adds commas to the number in the appropriate places. This
is achieved by first converting the float to a string. It does not
suit me that after conversion to a string that I will be adding commas
to a number that was different than the original passed into the
function. I was merely trying to determine if there was some sort of
workaround for this. I do not know all of the limitations of C++.

This is not a limitation of C++. It's rather a limitation of the way
floating point values are stored in computers. You claim to have
understood that, but it doesn't seem you really have. Anyway, you could
round the value to some number of digits, but I don't know how you
could do that if you don't know how many digits to round to.
The example I gave was just a constant. If I have a variable num of
type float with the value 35453.3466 then I don't want to add the
commas to a number that is different, say 35453.34656576. This holds
true for any floating-point number that may be passed into the
function.

Well, you can't just expect precision to come back magically after it
was reduced.
 
J

Julie

Bryan R. Meyer said:
I am a relatively new C++ programmer and am attempting to write a
function that takes a number of type float and adds commas to it in
the appropriate places. In order to manipulate the number to add the
commas, I convert it to a string (specifically a char[] rather than an
actual string object) using the
gcvt function as shown below.

char amt[50];
gcvt(amount,50,amt);

The problem I run into is a change in the precision. If amount is of
type float and has a value of 264588.44 then the code above results in
the string amt being "264588.4375". Note the change in the decimal
portion of the number; I don't want this. I want the original number
in the string. People have suggested using sprintf(). However,
sprintf() won't help me since I don't know the number of decimal
places in advance of the conversion.

Is there any way around this? Keep in mind that I don't know how many
decimal places I will need.

Short answer: no, there isn't a way around it as you describe using floating
point.

Long answer (and then some): go read the VB sub-thread.

Possible solution: move away from a floating point number and use (or create) a
fixed-point number. Once you have a fixed-point number, you won't have to
worry about loss/change of precision inherent w/ floating point, and then you
can convert to string and manipulate as you deem necessary.
 
E

E. Robert Tisdale

Bryan said:
I am a relatively new C++ programmer and am attempting to write a
function that takes a number of type float and adds commas to it
in the appropriate places. In order to manipulate the number
to add the commas, I convert it to a string
(specifically a char[] rather than an actual string object)
using the gcvt function as shown below.

char amt[50];
gcvt(amount, 50, amt);

The problem I run into is a change in the precision.
If amount is of type float and has a value of 264588.44
then the code above results in the string amt being "264588.4375".

But you requested 50 digits and you only got 10.
What does that tell you?
Note the change in the decimal portion of the number;

You probably meant the fractional part.
I don't want this.
I want the original number in the string.

I don't think so.
I think you want the original number in amount.
People have suggested using sprintf().
However, sprintf() won't help me since I don't know
the number of decimal places in advance of the conversion.

Is there any way around this? Keep in mind that
I don't know how many decimal places I will need.
cat main.cc
#include <iostream>
#include <stdlib.h>

int
main(int argc, char* argv[]) {
const
double amount = 264588.437543210987654321;
const
size_t ndigit = 50;
char amt[ndigit];
std::cout << gcvt(amount, ndigit, amt)
<< " = gcvt(amount, ndigit, amt)" << std::endl;
std::cout << gcvt(amount, 8, amt)
<< " = gcvt(amount, 8, amt)" << std::endl;
return 0;
}
g++ -Wall -ansi -pedantic -o main main.cc
./main
264588.43754321098 = gcvt(amount, ndigit, amt)
264588.44 = gcvt(amount, 8, amt)

It works just fine for me.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top