C - Printing out float values - c++

I have a C++ program that takes in values and prints out values like this:
getline(in,number);
cout << setw(10) << number << endl;
I have an equivalent C program that takes in values and prints out like so:
fscanf(rhs, "%e", &number);
printf("%lf\n", number);
But while the C++ program prints out, 0.30951 the C program prints out 0.309510. More examples: C++: 0.0956439 C: 0.095644. It seems to print the same results as long as the value is 7 digits long, but if its shorter the 7 digits, it adds an extra 0 at the end. And if its longer than 7 digits, it rounds down to 6 digits. I would like the C results to match the C++ program. Any help would be appreciated.
Thanks.
Note: number is a float and number are read from a file.

Take advantage of the length and precision specifiers in C++ iostreams
std::cout.precision(4);
std::cout << std::setw(10) << number << "\n";

Take advantage of the length and precision specifiers in C formatted print statements:
printf( "%6.4lf", number );
Prints four decimal places in a "cell" six characters wide.
You can use a wildcard character for either length or precision to provide that value at runtime:
int precision = 4;
printf( "%6.*lf", precision, number );

printf("%g\n", number);
Will solve your problem, %lf is used for double, %f is used for float, and %g is used for float when you want to display all the decimal places and cut off zeros.

Related

format floating point number to a char array of limited size with optional decimal point

I need to print out floating point numbers to a fixed number of chars. This is used in a strictly text-based data protocol (yes I know). Decimal is inclusive in character count. Ignore null terminator. There is no min padding requirement. Decimal precision can be 0 to (buffer size - 2) while max number of real numbers can be 0 to buffer size. Min and max value clamping to prevent truly out of range numbers are handled externally to this problem.
Examples with the assumption of a buffer size of 6 with enforcing min and max values of (0.0001 and 999999):
Original
Buffer (6 chars)
Notes
12445.11897784
12445
Only the 5 digts are kept as there is no room for decimal + value
8846.51548
8846.5
4.54631888315
4.5463
7651
7651
0.87457
.87457
0.8746 would also be acceptable
I thought sprintf with %.6G seemed to work at first until I realized it did not factor in the decimal point as a character. Is my understanding incomplete?
Is there any utilities in C++17 or lower I can use to accomplish the above. I am also willing to consider libraries that will or have become part of the standard in versions greater than c++17.
Here is a C++ 17 version:
#include <iostream>
#include <charconv>
std::string to6(float f) {
std::string s;
s.resize(10);
auto ec = std::to_chars(s.data(), s.data() + s.size(), f, std::chars_format::fixed);
s.resize(6);
if (s.back() == '.')
s.resize(5);
return s;
}
int main()
{
std::cout << to6(12445.11897784) << std::endl;
std::cout << to6(8846.51548) << std::endl;
std::cout << to6(4.54631888315) << std::endl;
std::cout << to6(7651) << std::endl;
std::cout << to6(0.87457) << std::endl;
return 0;
}
Note: I didn't check for errors, as
Min and max value clamping to prevent truly out of range numbers are handled externally to this problem.
Seems pretty straightforward:
If number is greater then 10000
Print it normally with no digits %.0f
If a number is greater then 1000
Print with one digit after comma %.1f
If a number is greater then 100
Print with two digits after comma %.2f
If a number is greater then 10
2. Print with 3 digits after comma %.3f
if ... 1
... %.4f
else
%.5f
Remove leading zero
Be ware of rounding! Ex. number 9.999999 is lower then 10, however it will get printed as 10.000. Because of that:
First print the number with greatest precision needed - %.5f - into a string.
Then count the digits before comma in the resulting string.
Then do the above comparisons "if a number is greater then 100" on the count of digits before the comma, rather then the actual number.
Trim the string to the needed count of digits after a comma.
Ie. work on the correctly rounded number that is in a string after printing, not before printing, that way you protect against any rounding changing your number while converting to a string.

Higher precision when parsing string to float

This is my first post here so sorry if it drags a little.
I'm assisting in some research for my professor, and I'm having some trouble with precision when I'm parsing some numbers that need to be precise to the 12th decimal point. For example, here is a number that I'm parsing from a string into an integer, before it's parsed:
-82.636097527336
Here is the code I'm using to parse it, which I also found on this site (thanks for that!):
std::basic_string<char> str = prelim[i];
std::stringstream s_str( str );
float val;
s_str >> val;
degrees.push_back(val);
Where 'prelim[i]' is just the current number I'm on, and 'degrees' is my new vector that holds all of the numbers after they've been parsed to a float. My issue is that, after it's parsed and stored in 'degrees', I do an 'std::cout' command comparing both values side-by-side, and shows up like this (old value (string) on the left, new value (float) on the right):
-82.6361
Does anyone have any insight into how I could alleviate this issue and make my numbers more precise? I suppose I could go character by character and use a switch case, but I think that there's an easier way to do it with just a few lines of code.
Again, thank you in advance and any pointers would be appreciated!
(Edited for clarity regarding how I was outputting the value)
Change to a double to represent the value more accurately, and use std::setprecision(30) or more to show as much of the internal representation as is available.
Note that the internal storage isn't exact; using an Intel Core i7, I got the following values:
string: -82.636097527336
float: -82.63610076904296875
double: -82.63609752733600544161163270473480224609
So, as you can see, double correctly represents all of the digits of your original input string, but even so, it isn't quite exact, since there are a few extra digits than in your string.
There are two problems:
A 32-bit float does not have enough precision for 14 decimal digits. From a 32-bit float you can get about 7 decimal digits, because it has a 23-bit binary mantissa. A 64-bit float (double) has 52 bits of mantissa, which gives you about 16 decimal digits, just enough.
Printing with cout by default prints six decimal digits.
Here is a little program to illustrate the difference:
#include <iomanip>
#include <iostream>
#include <sstream>
int main(int, const char**)
{
float parsed_float;
double parsed_double;
std::stringstream input("-82.636097527336 -82.636097527336");
input >> parsed_float;
input >> parsed_double;
std::cout << "float printed with default precision: "
<< parsed_float << std::endl;
std::cout << "double printed with default precision: "
<< parsed_double << std::endl;
std::cout << "float printed with 14 digits precision: "
<< std::setprecision(14) << parsed_float << std::endl;
std::cout << "double printed with 14 digits precision: "
<< std::setprecision(14) << parsed_double << std::endl;
return 0;
}
Output:
float printed with default precision: -82.6361
double printed with default precision: -82.6361
float printed with 14 digits precision: -82.636100769043
double printed with 14 digits precision: -82.636097527336
So you need to use a 64-bit float to be able to represent the input, but also remember to print with the desired precision with std::setprecision.
You cannot have precision up to the 12th decimal using a simple float. The intuitive course of action would be to use double or long double... but your are not going to have the precision your need.
The reason is due to the representation of real numbers in memory. You have more information here.
For example. 0.02 is actually stored as 0.01999999...
You should use a dedicated library for arbitrary precision, instead.
Hope this helps.

C++ printf printing doubles reads as 0

So I want to use printf so that I can make columns line up but printf can't seem to print doubles that need scientific notation. It just comes out as a 0 but with cout it comes out fine. 'in' and 'fn' are structs 'x' 'y' and 'z' are doubles
Code
printf("Facet Normal: %lf %15lf %15lf\n", in->fn.x, in->fn.y, in->fn.z);
cout << "cout test: " << in->fn.x << endl;
Output
Facet Normal: -0.000000 -0.894426 0.447215
cout test: -9.6137e-08
I can't seem to get printf to work correctly. I had the entire function working correctly with cout but like I said, I'd like things to line up niftily.
Edit:
As Oli said, using %e does get it to print correctly. By using %e throughout though it puts everything in scientific notation and a lot of the numbers in the data set don't in reality really need it. Cout seems to convert between %lf and %e as needed. Is there an easy way to get printf to get this behavior as well?
Answer:
%f is for both float and double (since float arguments are promoted to double);
%lf is for long double. f prints with no exponent, e prints with an exponent, and
g uses whichever looks better (following specific rules).
– Keith Thompson
%g gets the exact behavior I was looking for!
As the std::printf() reference says, just use %e:
std::printf( "One double in decimal scientific notation! %e" , my_double );
But the correct C++ way is to use std::cout and some manipulators, std::scientific in this case:
std::cout << "One double in decimal scientific notation!" << std::scientific << my_double;
Note that the format of std::cout forms part of its state, that is, you only have to configure it once, the format is applied to any output operation after the setting, and before other format change:
std::cout << std::scientific;
std::cout << std::pow( 10.0 , 10.0 ) << std::endl;
std::cout << std::pow( 10.0 , 20.0 ) << std::endl;
std::cout << std::pow( 10.0 , 30.0 ) << std::endl;
1e11
1e21
1e31
It seems you want to get the "best" formatting (which is the default for std::ostream): you can use %g (%Lg for long double) to have the formatting function decide how the values should be formatted. There are four format specifiers:
%f for fixed point notation (the format used by std::fixed for streams).
%e for scientific formatting (the format used by std::scientific for streams).
%g for the "best" version of fixed and scientific (the default for streams and since C++11 std::defaultfloat).
%a for an exact/hex representation of the floating point number (since C++11 std::hexfloat).
The formatting flags can used both in lowercase and uppercase to indicate whether any characters should be lowercase or uppercase (e.g. e vs. E). Note that the l length specifier is actually not relevant for the floating point formatting. You might need to use L, though, when formatting long double
If you want to control the output from std::cout, use setw() and setfill().
http://www.cplusplus.com/reference/iomanip/setw/
You can also set the precision, etc. I will leave that to you to explore.

C++ significant figures

How can I do math involving significant figures in C++? I want this to work correct with measured data from chemistry and physics experiments. An example: 65 / 5 = 10. I would need to get rid of unneeded decimal places and replace some digits with 0s.
Thanks!
This should get you what you need:
std::cout.precision(x); // x would be the number of significant figures to output
This may not be the most efficient way, but you can create a custom sig fig data type.
class SigFigFloat
{
SigFigFloat(vector<short> digits, int decimalIndex, bool negative);
SigFigFloat operator+(const SigFigFloat &value);
SigFigFloat operator-(const SigFigFloat &value);
//etc...
}
It can be a lot of work, but if you implement this right, it can be a really flexible way to represent and do calculations with sig figs.
It is hard because significant figures are a decimal concept, and computers speak binary. You can use decimal number classes (I don't know of any), or use boost::interval, which is the closest to what you certainly want to achieve.
That depends on how you are displaying them. If you are using the printf-family, you set the precision (sprintf(buffer, "%.2f", myfloat)). If you are using ostreams, you call the precision function to set the number of decimal places. If you are looking for the more scientific method of sig figs, you'll have to write a custom function that determines the precision based on the current value of the float.
You can also:
#define SIGNIFICANT_DIGITS 3
const float SIGNIFICANT_DIGITS_PWR = powf(10.0f, SIGNIFICANT_DIGITS);
float f;
std::cin >> f;
int int_digits = (int)log10f(f) + 1;
if (int_digits > 1) {
float prod = SIGNIFICANT_DIGITS_PWR / powf(10.0f, int_digits);
f = (float)(int)(f * prod) / prod;
} else {
f = (float)((int)(f * SIGNIFICANT_DIGITS_PWR)) / SIGNIFICANT_DIGITS_PWR;
};
std::cout << f << '\n';
Output:
0.1234
> 0.123
12.34
> 12.3
1234
> 1230
here is a quick C++11 solution that worked for me:
int sig_figs = 3;
double number = 1562.654478;
std::cout << "original number:" << number << std::endl;
number = ([number](int number_of_sig_figs)->double{
std::stringstream lStream;
lStream << std::setprecision(number_of_sig_figs) << number;
return std::stod(lStream.str());
})(sig_figs);
std::cout << "rounded number:" << number << std::endl;
Well there are good math libraries in math.h
Also storing your figures in floats, doubles or long doubles will allow for more precise operations.
Floats offer 7 significant digits while doubles offer 16 significant digits.
source
Also when printing out usually people use _snprintf or printf and you can format those doubles, floats to the precision you want like:
Float Precision
printf("Value %8.2f", floatVariable);
This says you require a total
field of 8 characters, within the 8
characters the last 2 will hold the
decimal part.
_snprintf(buffer, sizeof(buffer), "Value %.2f", floatVariable);
The example above
requests the minimum field width and
the last two characters are to hold
the decimal part.

Convert a double to fixed decimal point in C++

I have a double variable in C++ and want to print it out to the screen as a fixed decimal point number.
Basically I want to know how to write a function that takes a double and a number of decimal places and prints out the number to that number of decimal places, zero padding if necessary.
For example:
convert(1.235, 2)
would print out
1.24
and
convert(1, 3)
would print out
1.000
so the function works as
convert(number as double, number of decimal places)
and simply prints out the required value to standard output (cout).
Does anyone know how to do this?
Thanks in advance.
Assuming I'm remembering my format strings correctly,
printf("%.*f", (int)precision, (double)number);
Look at the setprecision manipulator which should give you the idea
There is no such thing as a "fixed decimal place" number. The convert function will need to be the function that actually prints it out. I would suggest getting the whole part of the number, then print it. If [decimal places]>0 then print a decimal place, then print each decimal individually like: floor((n*log(10,d))%10); <-- just an idea, not actual code.
#include <iomanip>
#include <iostream.h>
// print a float, x places of precision
void convert (double number, int x)
{
cout << setprecision(x) << number << endl;
}
int main()
{
double a = 1.234;
convert (a,2);
}
output: 1.23
reference