Converting a precision double to a string - c++

I have a large number in c++ stored as a precise double value (assuming the input 'n' is 75): 2.4891e+109
Is there any way to convert this to a string or an array of each individual digit?
Here's my code so far, although it's not entirely relevant to the question:
int main(){
double n = 0;
cout << "Giz a number: ";
cin >> n;
double val = 1;
for(double i = 1; i <= n; i++){
val = val * i;
}
//Convert val to string/array here?
}

std::stringstream str;
str << fixed << setprecision( 15 ) << yournumber;
You may also be interested in the scientific format flag.
C++11 also has a few interesting functions std::to_string which you may want to check out!

What's wrong with the standard way?
std::stringstream ss;
ss << val;
std::string s = ss.str();
Additionally, C++11 allows:
std::string s = std::to_string(val);
If you need performance you might find that the memory allocations involved above are too expensive, in which case you could resort to snprintf, the deprecated strstream, or perhaps direct use of the num_put facet. For example:
char c[30];
std::snprintf(c,sizeof c,"%e",val);

You will find that the double value is not as precise as you think. It only contains 53 bits of precision, or about 15-17 digits; after that it starts rounding each result. Your number requires much more precision than that if you want an exact answer, 92 digits actually or 364 bits.

std::cout << setprecision(5) << val;
as in http://www.cprogramming.com/tutorial/iomanip.html

Related

how to take a double's fraction part and turn it into an integer? (c++)

my goal is to turn a double's fraction part into an integer, for example: turn 0.854 into 854 or turn 0.9321 into 9321 (the whole part of the double is always 0)
i was doing it like this, but i dont know how to fill the while's parameters to make it stop when variable x becomes a whole number without a fraction:
double x;
cin >> x;
while(WHAT DO I TYPE HERE TO MAKE IT STOP WHEN X BECOMES A WHOLE NUMBER){
x *= 10;
}
it would be best if i could do it with a loop, but if it is not possible, i am open to other suggestions :)
That question has no answer in a mathematical/logical sense. You have to read how floating point numbers in computers work, see e.g.
https://en.wikipedia.org/wiki/Floating-point_arithmetic
and understand that they are not decimal point numbers in memory. A floating point number in memory consists of three actual numbers: significant * base^{exponent} and according to IEEE the base used is "2" in basically any modern floating point data, but in even more generality, the base can be anything. Thus, whatever you have in your mind, or even see on your screen as output, is a misleading representation of the data in memory. Your question is, thus, mainly a misconception of how floating point numbers in computers work...
Thus, what you specifically ask for does in general not exist and cannot be done.
However, there may be special application for output formatting or whatever where something like this may make sense -- but then the specific goal must be clearly stated in the question here. And in some of such cases, using a "string-based" approach, as you suggested, will work. But this is not an answer to your generic question and has the high potential to also mislead others in the future.
Actually, one way to make your question obvious and clear is to also specify a fixed desired precision, thus, numbers after the decimal point. Then the answer is quite trivially and correctly:
long int value = fraction * pow(10, precision);
In this scenario you know 100% what your are doing. And if you really like you could subsequently remove zeros from the right side...
int nTrailingZeros = 0;
while (value%10 == 0) {
value /= 10;
++nTrailingZeros;
}
However there is another principle problem on a numerical level: there is no mathematical difference between, e.g., 000003 and just 3, thus in any such application the input 0.000003 will give the same results as 0.0003 or 0.3 etc. This cannot be a desired functionality... it is pretty useless to ask about the *value of the fractional part of a floating point number. But, since we have a known precision`, we can do:
cout << setw(precision-ntrailing) << setfill('0') << value << endl;
which will fill in the eventually missing leading zeros.
See this complete tested test code
#include <iostream>
#include <iomanip>
#include <cmath>
using namespace std;
int main() {
double v = 0.0454243252;
int precision = 14;
long int value = v*pow(10,precision);
cout << value << endl;
// 4542432520000
int nTrailingZeros = 0;
while (value%10 == 0) {
value /= 10;
++nTrailingZeros;
}
cout << value << endl;
// 454243252
cout << setw(precision-ntrailing) << setfill('0') << value << endl;
// 0454243252
}
Here is a possible approach:
#include <iostream>
#include <string>
#include <sstream>
#include <iomanip>
using namespace std;
int main()
{
cout << "Enter Number: ";
double user_input;
cin >> user_input;
int user_input_to_int = int(user_input);
double decimal_value = user_input - user_input_to_int;
ostringstream oss;
oss << std::noshowpoint << decimal_value;
string num_str = oss.str();
int str_length = num_str.size()-2;
int multiplier = 1;
for (int x = 0; x < str_length; x++)
{
multiplier *= 10;
}
cout << "\n";
cout << "Whole number: " << user_input_to_int << endl;
cout << "Decimal value: " << decimal_value*multiplier << endl;
}
Compare the difference between double and integer part. It is working only if x is less than 2^63.
while (x - long long(x) > 0)
find 2 real numbers find the fractional part smaller than these numbers

Is it possible to cut of zeros in float converted to a string in C++? [duplicate]

How do you convert a float to a string in C++ while specifying the precision & number of decimal digits?
For example: 3.14159265359 -> "3.14"
A typical way would be to use stringstream:
#include <iomanip>
#include <sstream>
double pi = 3.14159265359;
std::stringstream stream;
stream << std::fixed << std::setprecision(2) << pi;
std::string s = stream.str();
See fixed
Use fixed floating-point notation
Sets the floatfield format flag for the str stream to fixed.
When floatfield is set to fixed, floating-point values are written using fixed-point notation: the value is represented with exactly as many digits in the decimal part as specified by the precision field (precision) and with no exponent part.
and setprecision.
For conversions of technical purpose, like storing data in XML or JSON file, C++17 defines to_chars family of functions.
Assuming a compliant compiler (which we lack at the time of writing),
something like this can be considered:
#include <array>
#include <charconv>
double pi = 3.14159265359;
std::array<char, 128> buffer;
auto [ptr, ec] = std::to_chars(buffer.data(), buffer.data() + buffer.size(), pi,
std::chars_format::fixed, 2);
if (ec == std::errc{}) {
std::string s(buffer.data(), ptr);
// ....
}
else {
// error handling
}
The customary method for doing this sort of thing is to "print to string". In C++ that means using std::stringstream something like:
std::stringstream ss;
ss << std::fixed << std::setprecision(2) << number;
std::string mystring = ss.str();
You can use C++20 std::format:
#include <format>
int main() {
std::string s = std::format("{:.2f}", 3.14159265359); // s == "3.14"
}
or the fmt::format function from the {fmt} library, std::format is based on (godbolt):
#include <fmt/core.h>
int main() {
std::string s = fmt::format("{:.2f}", 3.14159265359); // s == "3.14"
}
where 2 is a precision.
It is not only shorter than using iostreams or sprintf but also significantly faster and is not affected by the locale.
Another option is snprintf:
double pi = 3.1415926;
std::string s(16, '\0');
auto written = std::snprintf(&s[0], s.size(), "%.2f", pi);
s.resize(written);
Demo. Error handling should be added, i.e. checking for written < 0.
Here a solution using only std. However, note that this only rounds down.
float number = 3.14159;
std::string num_text = std::to_string(number);
std::string rounded = num_text.substr(0, num_text.find(".")+3);
For rounded it yields:
3.14
The code converts the whole float to string, but cuts all characters 2 chars after the "."
Here I am providing a negative example where your want to avoid when converting floating number to strings.
float num=99.463;
float tmp1=round(num*1000);
float tmp2=tmp1/1000;
cout << tmp1 << " " << tmp2 << " " << to_string(tmp2) << endl;
You get
99463 99.463 99.462997
Note: the num variable can be any value close to 99.463, you will get the same print out. The point is to avoid the convenient c++11 "to_string" function. It took me a while to get out this trap. The best way is the stringstream and sprintf methods (C language). C++11 or newer should provided a second parameter as the number of digits after the floating point to show. Right now the default is 6. I am positing this so that others won't wast time on this subject.
I wrote my first version, please let me know if you find any bug that needs to be fixed. You can control the exact behavior with the iomanipulator. My function is for showing the number of digits after the decimal point.
string ftos(float f, int nd) {
ostringstream ostr;
int tens = stoi("1" + string(nd, '0'));
ostr << round(f*tens)/tens;
return ostr.str();
}

C++ convert small double to string and back to double [duplicate]

How do you convert a float to a string in C++ while specifying the precision & number of decimal digits?
For example: 3.14159265359 -> "3.14"
A typical way would be to use stringstream:
#include <iomanip>
#include <sstream>
double pi = 3.14159265359;
std::stringstream stream;
stream << std::fixed << std::setprecision(2) << pi;
std::string s = stream.str();
See fixed
Use fixed floating-point notation
Sets the floatfield format flag for the str stream to fixed.
When floatfield is set to fixed, floating-point values are written using fixed-point notation: the value is represented with exactly as many digits in the decimal part as specified by the precision field (precision) and with no exponent part.
and setprecision.
For conversions of technical purpose, like storing data in XML or JSON file, C++17 defines to_chars family of functions.
Assuming a compliant compiler (which we lack at the time of writing),
something like this can be considered:
#include <array>
#include <charconv>
double pi = 3.14159265359;
std::array<char, 128> buffer;
auto [ptr, ec] = std::to_chars(buffer.data(), buffer.data() + buffer.size(), pi,
std::chars_format::fixed, 2);
if (ec == std::errc{}) {
std::string s(buffer.data(), ptr);
// ....
}
else {
// error handling
}
The customary method for doing this sort of thing is to "print to string". In C++ that means using std::stringstream something like:
std::stringstream ss;
ss << std::fixed << std::setprecision(2) << number;
std::string mystring = ss.str();
You can use C++20 std::format:
#include <format>
int main() {
std::string s = std::format("{:.2f}", 3.14159265359); // s == "3.14"
}
or the fmt::format function from the {fmt} library, std::format is based on (godbolt):
#include <fmt/core.h>
int main() {
std::string s = fmt::format("{:.2f}", 3.14159265359); // s == "3.14"
}
where 2 is a precision.
It is not only shorter than using iostreams or sprintf but also significantly faster and is not affected by the locale.
Another option is snprintf:
double pi = 3.1415926;
std::string s(16, '\0');
auto written = std::snprintf(&s[0], s.size(), "%.2f", pi);
s.resize(written);
Demo. Error handling should be added, i.e. checking for written < 0.
Here a solution using only std. However, note that this only rounds down.
float number = 3.14159;
std::string num_text = std::to_string(number);
std::string rounded = num_text.substr(0, num_text.find(".")+3);
For rounded it yields:
3.14
The code converts the whole float to string, but cuts all characters 2 chars after the "."
Here I am providing a negative example where your want to avoid when converting floating number to strings.
float num=99.463;
float tmp1=round(num*1000);
float tmp2=tmp1/1000;
cout << tmp1 << " " << tmp2 << " " << to_string(tmp2) << endl;
You get
99463 99.463 99.462997
Note: the num variable can be any value close to 99.463, you will get the same print out. The point is to avoid the convenient c++11 "to_string" function. It took me a while to get out this trap. The best way is the stringstream and sprintf methods (C language). C++11 or newer should provided a second parameter as the number of digits after the floating point to show. Right now the default is 6. I am positing this so that others won't wast time on this subject.
I wrote my first version, please let me know if you find any bug that needs to be fixed. You can control the exact behavior with the iomanipulator. My function is for showing the number of digits after the decimal point.
string ftos(float f, int nd) {
ostringstream ostr;
int tens = stoi("1" + string(nd, '0'));
ostr << round(f*tens)/tens;
return ostr.str();
}

How to format doubles in the following way?

I am using C++ and I would like to format doubles in the following obvious way. I have tried playing with 'fixed' and 'scientific' using stringstream, but I am unable to achieve this desired output.
double d = -5; // print "-5"
double d = 1000000000; // print "1000000000"
double d = 3.14; // print "3.14"
double d = 0.00000000001; // print "0.00000000001"
// Floating point error is acceptable:
double d = 10000000000000001; // print "10000000000000000"
As requested, here are the things I've tried:
#include <iostream>
#include <string>
#include <sstream>
#include <iomanip>
using namespace std;
string obvious_format_attempt1( double d )
{
stringstream ss;
ss.precision(15);
ss << d;
return ss.str();
}
string obvious_format_attempt2( double d )
{
stringstream ss;
ss.precision(15);
ss << fixed;
ss << d;
return ss.str();
}
int main(int argc, char *argv[])
{
cout << "Attempt #1" << endl;
cout << obvious_format_attempt1(-5) << endl;
cout << obvious_format_attempt1(1000000000) << endl;
cout << obvious_format_attempt1(3.14) << endl;
cout << obvious_format_attempt1(0.00000000001) << endl;
cout << obvious_format_attempt1(10000000000000001) << endl;
cout << endl << "Attempt #2" << endl;
cout << obvious_format_attempt2(-5) << endl;
cout << obvious_format_attempt2(1000000000) << endl;
cout << obvious_format_attempt2(3.14) << endl;
cout << obvious_format_attempt2(0.00000000001) << endl;
cout << obvious_format_attempt2(10000000000000001) << endl;
return 0;
}
That prints the following:
Attempt #1
-5
1000000000
3.14
1e-11
1e+16
Attempt #2
-5.000000000000000
1000000000.000000000000000
3.140000000000000
0.000000000010000
10000000000000000.000000000000000
There is no way for a program to KNOW how to format the numbers in the way that you are describing, unless you write some code to analyze the numbers in some way - and even that can be quite hard.
What is required here is knowing the input format in your source code, and that's lost as soon as the compiler converts the decimal input source code into binary form to store in the executable file.
One alternative that may work is to output to a stringstream, and then from that modify the output to strip trailing zeros. Something like this:
string obvious_format_attempt2( double d )
{
stringstream ss;
ss.precision(15);
ss << fixed;
ss << d;
string res = ss.str();
// Do we have a dot?
if ((string::size_type pos = res.rfind('.')) != string::npos)
{
while(pos > 0 && (res[pos] == '0' || res[pos] == '.')
{
pos--;
}
res = res.substr(pos);
}
return res;
}
I haven't actually tired it, but as a rough sketch, it should work. Caveats are that if you have something like 0.1, it may well print as 0.09999999999999285 or some such, becuase 0.1 can not be represented in exact form as a binary.
Formatting binary floating-point numbers accurately is quite tricky and was traditionally wrong. A pair of papers published in 1990 in the same journal settled that decimal values converted to binary floating-point numbers and back can have their values restored assuming they don't use more decimal digits than a specific constraint (in C++ represented using std::numeric_limits<T>::digits10 for the appropriate type T):
Clinger's "How to read floating-point numbers accurately" describes an algorithm to convert from a decimal representation to a binary floating-point.
Steele/White's "How to print floating-point numbers accurately" describes how to convert from a binary floating-point to a decimal decimal value. Interestingly, the algorithm even converts to the shortest such decimal value.
At the time these papers were published the C formatting directives for binary floating points ("%f", "%e", and "%g") were well established and they didn't get changed to the take the new results into account. The problem with the specification of these formatting directives is that "%f" assumes to count the digits after the decimal point and there is no format specifier asking to format numbers with a certain number of digits but not necessarily starting to count at the decimal point (e.g., to format with a decimal point but potentially having many leading zeros).
The format specifiers are still not improved, e.g., to include another one for non-scientific notation possibly involving many zeros, for that matter. Effectively, the power of the Steele/White's algorithm isn't fully exposed. The C++ formatting, sadly, didn't improve over the situation and just delegates the semantics to the C formatting directives.
The approach of not setting std::ios_base::fixed and using a precision of std::numeric_limits<double>::digits10 is the closest approximation of floating-point formatting the C and C++ standard libraries offer. The exact format requested could be obtained by getting the digits using using formatting with std::ios_base::scientific, parsing the result, and rewriting the digits afterwards. To give this process a nice stream-like interface it could be encapsulated with a std::num_put<char> facet.
An alternative could be the use of Double-Conversion. This implementation uses an improved (faster) algorithm for the conversion. It also exposes interfaces to get the digits in some form although not directly as a character sequence if I recall correctly.
You can't do what you want to do, because decimal numbers are not representable exactly in floating point format. In otherwords, double can't precisely hold 3.14 exactly, it stores everything as fractions of powers of 2, so it stores it as something like 3 + 9175/65536 or thereabouts (do it on your calculator and you'll get 3.1399993896484375. (I realize that 65536 is not the right denominator for IEEE double, but the gist of it is correct).
This is known as the round trip problem. You can't reliable do
double x = 3.14;
cout << magic << x;
and get "3.14"
If you must solve the round-trip problem, then don't use floating point. Use a custom "decimal" class, or use a string to hold the value.
Here's a decimal class you could use:
https://stackoverflow.com/a/15320495/364818
I am using C++ and I would like to format doubles in the following obvious way.
Based on your samples, I assume you want
Fixed rather than scientific notation,
A reasonable (but not excessive) amount of precision (this is for user display, so a small bit of rounding is okay),
Trailing zeros truncated, and
Decimal point truncated as well if the number looks like an integer.
The following function does just that:
#include <cmath>
#include <iomanip>
#include <sstream>
#include <string>
std::string fixed_precision_string (double num) {
// Magic numbers
static const int prec_limit = 14; // Change to 15 if you wish
static const double log10_fuzz = 1e-15; // In case log10 is slightly off
static const char decimal_pt = '.'; // Better: use std::locale
if (num == 0.0) {
return "0";
}
std::string result;
if (num < 0.0) {
result = '-';
num = -num;
}
int ndigs = int(std::log10(num) + log10_fuzz);
std::stringstream ss;
if (ndigs >= prec_limit) {
ss << std::fixed
<< std::setprecision(0)
<< num;
result += ss.str();
}
else {
ss << std::fixed
<< std::setprecision(prec_limit-ndigs)
<< num;
result += ss.str();
auto last_non_zero = result.find_last_not_of('0');
if (result[last_non_zero] == decimal_pt) {
result.erase(last_non_zero);
}
else if (last_non_zero+1 < result.length()) {
result.erase(last_non_zero+1);
}
}
return result;
}
If you are using a computer that uses IEEE floating point, changing prec_limit to 16 is unadvisable. While this will let you properly print 0.9999999999999999 as such, it also prints 5.1 as 5.0999999999999996 and 9.99999998 as 9.9999999800000001. This is from my computer, your results may vary due to a different library.
Changing prec_limit to 15 is okay, but it still leads to numbers that don't print "correctly". The value specified (14) works nicely so long as you aren't trying to print 1.0-1e-15.
You could do even better, but that might require discarding the standard library (see Dietmar Kühl's answer).

taking big integer input all at a time in C++

i want to take a 1000 digit integer input all at a time,& want to add the digits separately.is there any input method to take such a large input?
You need to input that as a string. Split them, and convert each character to an integer. Add them up, and you're done.
Example, this number here (randomly generated):
9624526619162264306083309360203157186784123851390498919674886891002552146753945797326679482200717699585297042606470048297021049209667042255911984240697992738371633115195140494325737382583412562136836759072897211537655046343769659111215754043609344618490646811291135643554115350431099553593485744944746093896695837300975718819726339233383800764568364950577294931831936979504756278187812548901366714205562309364234394802723329400976924082450161974562063268243689930750925213262044910428021004262080895556879515597779404780565380480750286553508081070834339176079062215815331059349488936312244526697733596052063044560959189161656978673936732284706841120711543620038686227462170335634371808995466024671420024705248851244350701111587608201303840696489479021196275228499780922745352396928865910631672384263395712487735712098161853665189905194589355110620257494673972892816413534347360049692019184831019218764766067298983043791063184786671132332077197148683743991683245617836086353821268720434176862469084808
And here's the C++ program:
int strint(std::string &str) {
int i;
std::stringstream intstr(str);
intstr >> i;
return i;
}
int main () {
std::string strdigit, schar;
int sum = 0;
std::cout << "Enter Digits: ";
std::cin >> strdigit;
std::stringstream ss;
for (int i = 0; i < strdigit.length(); i++) {
ss.clear();
ss << strdigit[i];
ss >> schar;
sum += strint(schar);
}
std::cout << sum;
}
The sum is: 4479
Simply read the digits into a string and use std::accumulate. For example:
std::string str("1234567890"); // your number here
int result = std::accumulate(str.begin(), str.end(), 0, [](int val, char ch)
{
return val + (ch - '0');
});
std::cout << result << '\n'; // display the answer
You need a library to provide support for this.
Read the digits into a string and use a multiprecision math library such as GMP to do the addition. The library should have functions for converting between digit strings and the library's internal representation for numbers.
(Actually, it looks like GMP can read digits directly from an istream, so you may not even need a string.)
I'm a little unclear on the question. If you are adding the digits separately, then I would have thought you were treating it more as a string than an integer (at least, until you start adding up the digits).
Can you clarify how the 1,000-digit integer needs to be stored in memory?
As marlon suggested, why not simply use good 'ol for loop and string?
int main() {
string str = "3985792792679283635";
int len = str.length();
int sum = 0;
for(int i = 0; i < len; i++) {
sum += str[i] - '0';
}
cout << sum << endl;
}