Convert boost::multiprecision::cpp_dec_float_100 to string with precision - c++

In my code I want to have a function which performs some calculations based on boost::multiprecision::cpp_dec_float_100 and returns string as a result with some precision, but the question is how I should set the precision ? e.g. If the precision is 9, then I expect the following results for the following numbers:
for 2345.12345678910111213 I expect string "2345.123456789" but I have 12345.1235
for 1.12345678910111213 I expect string "1.123456789" but I have 1.12345679
So it always returns my exact number of characters provided to str() function with round. I know that I can do it like e.g. this:
std::stringstream ss;
ss << std::fixed << std::setprecision(9) << my_value;
return ss.str();
or use cout(but this is not my case) or do some find on string to find "." and take only 9 characters after it, but can I do it in an easier way ? maybe in boost is some function to do it correctly ?
#include <iostream>
#include <boost/multiprecision/cpp_dec_float.hpp>
namespace bmp = boost::multiprecision;
std::string foo_1()
{
bmp::cpp_dec_float_100 val{"12345.12345678910111213"};
return val.str(9);
}
std::string foo_2()
{
bmp::cpp_dec_float_100 val{"1.12345678910111213"};
return val.str(9);
}
int main()
{
auto const val_1 = foo_1();
auto const val_2 = foo_2();
std::cout << "val_1: " << val_1 << std::endl;
std::cout << "val_2: " << val_2 << std::endl;
return 0;
}
online version: https://wandbox.org/permlink/HTAHsE5ZE3tgK9kf

Change the line:
return val.str(9);
To:
return val.str(9, std::ios::fixed);
You will get the expected strings.

Related

How to remove trailing zeros with scientific notation when convert double to string?

Live On Coliru
FormatFloat
I try to implement one conversion of Golang strconv.FormatFloat() in C++.
#include <sstream>
#include <iostream>
#include <string>
#include <iomanip>
using namespace std;
std::string convert_str(double d)
{
std::stringstream ss;
if (d >= 0.0001)
{
ss << std::fixed << std::setprecision(4); // I know the precision, so this is fine
ss << d;
return ss.str();
}
else
{
ss << std::scientific;
ss << d;
return ss.str();
}
}
int main()
{
std::cout << convert_str(0.002) << std::endl; // 0.0020
std::cout << convert_str(0.00001234560000) << std::endl; // 1.234560e-05
std::cout << convert_str(0.000012) << std::endl; // 1.200000e-05
return 0;
}
Output:
0.0020
1.234560e-05 // should be 1.23456e-05
1.200000e-05 // should be 1.2e-05
Question> How can I setup the output modifier so that the trailing zero doesn't show up?
strconv.FormatFloat(num, 'e', -1, 64)
The special precision value (-1) is used for the smallest number of
digits necessary such that ParseFloat() will return f exactly.
At the risk of being heavily downvoted criticised for posting a C answer to a C++ question ... you can use the %lg format specifier in a call to sprintf.
From cpprefernce:
Unless alternative representation is requested the trailing zeros are
removed, also the decimal point character is removed if no fractional
part is left.
So, if you only want to remove the trailing zeros when using scientific notation, you can change your convert_str function to something like the following:
std::string convert_str(double d)
{
if (d >= 0.0001) {
std::stringstream ss;
ss << std::fixed << std::setprecision(4); // I know the precision, so this is fine
ss << d;
return ss.str();
}
else {
char cb[64];
sprintf(cb, "%lg", d);
return cb;
}
}
For the three test cases in your code, this will give:
0.0020
1.23456e-05
1.2e-05
From C++20 and later, the std::format class may offer a more modern alternative; however, I'm not (yet) fully "up to speed" with that, so I cannot present a solution using it. Others may want to do so.
Yes, std::scientific don't remove trailing zeros from scientific notation. The good news, for your specific case, is that cout already format values below 0.0001 using scientific notation, and removing trailing zeros. So you can let your code like this:
#include <sstream>
#include <iostream>
#include <string>
#include <iomanip>
using namespace std;
std::string convert_str(double d)
{
std::stringstream ss;
if (d >= 0.0001)
{
ss << std::fixed << std::setprecision(4); // I know the precision, so this is fine
ss << d;
return ss.str();
}
else
{
ss << d;
return ss.str();
}
}
int main()
{
std::cout << convert_str(0.002) << std::endl; // 0.0020
std::cout << convert_str(0.00001234560000) << std::endl; // 1.23456e-05
std::cout << convert_str(0.000012) << std::endl; // 1.2e-05
return 0;
}
The wanted output can be generated with a combination of the std::setprecision and std::defaultfloat manipulators:
std::cout << std::setprecision(16) << std::defaultfloat
<< 0.002 << '\n'
<< 0.00001234560000 << '\n'
<< 0.000012 << '\n';
Live at: https://godbolt.org/z/67fWa1seo

Why is my string extraction function using back referencing in regex not working as intended?

Extraction Function
string extractStr(string str, string regExpStr) {
regex regexp(regExpStr);
smatch m;
regex_search(str, m, regexp);
string result = "";
for (string x : m)
result = result + x;
return result;
}
The Main Code
#include <iostream>
#include <regex>
using namespace std;
string extractStr(string, string);
int main(void) {
string test = "(1+1)*(n+n)";
cout << extractStr(test, "n\\+n") << endl;
cout << extractStr(test, "(\\d)\\+\\1") << endl;
cout << extractStr(test, "([a-zA-Z])[+-/*]\\1") << endl;
cout << extractStr(test, "([a-zA-Z])[+-/*]([a-zA-Z])") << endl;
return 0;
}
The Output
String = (1+1)*(n+n)
n\+n = n+n
(\d)\+\1 = 1+11
([a-zA-Z])[+-/*]\1 = n+nn
([a-zA-Z])[+-/*]([a-zA-Z]) = n+nnn
If anyone could kindly point the error I've done or point me to a similar question in SO that I've missed while searching, it would be greatly appreciated.
Regexes in C++ don't work quite like "normal" regexes. Specialy when you are looking for multiple groups later. I also have some C++ tips in here (constness and references).
#include <cassert>
#include <iostream>
#include <sstream>
#include <regex>
#include <string>
// using namespace std; don't do this!
// https://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice
// pass strings by const reference
// 1. const, you promise not to change them in this function
// 2. by reference, you avoid making copies
std::string extractStr(const std::string& str, const std::string& regExpStr)
{
std::regex regexp(regExpStr);
std::smatch m;
std::ostringstream os; // streams are more efficient for building up strings
auto begin = str.cbegin();
bool comma = false;
// C++ matches regexes in parts so work you need to loop
while (std::regex_search(begin, str.end(), m, regexp))
{
if (comma) os << ", ";
os << m[0];
comma = true;
begin = m.suffix().first;
}
return os.str();
}
// small helper function to produce nicer output for your tests.
void test(const std::string& input, const std::string& regex, const std::string& expected)
{
auto output = extractStr(input, regex);
if (output == expected)
{
std::cout << "test succeeded : output = " << output << "\n";
}
else
{
std::cout << "test failed : output = " << output << ", expected : " << expected << "\n";
}
}
int main(void)
{
std::string input = "(1+1)*(n+n)";
test(input, "n\\+n", "n+n");
test(input, "(\\d)\\+\\1", "1+1");
test(input, "([a-zA-Z])[+-/*]\\1", "n+n");
return 0;
}

C++: converting wstring to double

Before converting wstring to double - how to validate it with regex? Java no problem, but C++ raising questions.. :)
I suppose you have a string and you want to know if it is a double or not. The following code does not use regular expressions. Instead it initializes a stringstream and reads a double from it. If the string starts with something non-numeric, then ss.fail() will be set. If it starts with a number, but does not read the whole string, then there's something non-numeric at the end of the string. So if everything went well and the string is really only a number, then ss.eof() && !ss.fail() will be true.
#include <iostream>
#include <sstream>
int main()
{
std::stringstream ss("123.456");
double mydouble;
ss >> mydouble;
if (ss.eof() && !ss.fail())
std::cout << "yay, success: " << mydouble << std::endl;
else
std::cout << "that was not a double." << std::endl;
return 0;
}
There's also std::wstringstream if you need to convert wide character strings.
You might also want to have a look at the boost libraries, especially at Boost.Lexical_Cast.
With this library you could do the following:
#include <boost/lexical_cast.hpp>
#include <iostream>
int main()
{
try
{
double mydouble = boost::lexical_cast<double>("123.456");
std::cout << "yay, success: " << mydouble << std::endl;
}
catch(const boost::bad_lexical_cast &)
{
std::cout << "that was not a double." << std::endl;
}
return 0;
}
Or maybe it is simpler to do that this way:
std::wstring strKeyValue = "147.sd44";
double value = (double) _wtof(strKeyValue.c_str());
And if strKeyValue==0 then it means it's not double.

c++ double to string shows floating points

I have a string: (66)
Then I convert it to double and do some math: atof(t.c_str()) / 30
then I convert it back to string: string s = boost::lexical_cast<string>(hizdegerd)
Problem is when I show it on label it becomes 2,20000001.
I've tried everything. sprintf etc.
I want to show only one digit after point.
hizdegerd = atof(t.c_str()) / 30;
char buffer [50];
hizdegerd=sprintf (buffer, "%2.2f",hizdegerd);
if(oncekideger != hizdegerd)
{
txtOyunHiz->SetValue(hizdegerd);
oncekideger = hizdegerd;
}
I think I'd wrap the formatting up into a function template, something like this:
#include <iostream>
#include <sstream>
#include <iomanip>
template <class T>
std::string fmt(T in, int width = 0, int prec = 0) {
std::ostringstream s;
s << std::setw(width) << std::setprecision(prec) << in;
return s.str();
}
int main(){
std::string s = fmt(66.0 / 30.0, 2, 2);
std::cout << s << "\n";
}
You can use this way of conversion back to string and then only the wished number of digits for the precision will be taken in consideration:
ostringstream a;
a.precision(x); // the number of precision digits will be x-1
double b = 1.45612356;
a << b;
std::string s = a.str();
Since you wrote "I want to show":
#include<iostream>
#include<iomanip>
int main()
{
std::cout << std::fixed << std::setprecision(1) << 34.2356457;
}
Output:
34.2
By the way, sprintf is buffer-overflow-vulnerable and is not C++ .

Convert a string into a double, and a int. How to?

I'm having trouble converting a string into a double.
My string has been declared using the "string" function, so my string is:
string marks = "";
Now to convert it to a double I found somewhere on the internet to use word.c_str(), and so I did. I called it and used it like this:
doubleMARK = strtod( marks.c_str() );
This is similar to the example I found on the web:
n1=strtod( t1.c_str() );
Apparently, that's how it's done. But of course, it doesn't work. I need another parameter. A pointer I believe? But I'm lost at this point as to what I'm suppose to do. Does it need a place to store the value or something? or what?
I also need to convert this string into a integer which I have not begun researching as to how to do, but once I find out and if I have errors, I will edit this out and post them here.
Was there a reason you're not using std::stod and std::stoi? They are at least 9 levels more powerful than flimsy strtod.
Example
#include <iostream>
#include <string>
int main() {
using namespace std;
string s = "-1";
double d = stod(s);
int i = stoi(s);
cout << s << " " << d << " " << i << endl;
}
Output
-1 -1 -1
If you must use strtod, then just pass NULL as the second parameter. According to cplusplus.com:
If [the second parameter] is not a null pointer, the function also sets the value pointed by endptr to point to the first character after the number.
And it's not required to be non-NULL.
Back in the Bad Old Dark Days of C, I'd do something ugly and unsafe like this:
char sfloat[] = "1.0";
float x;
sscanf (sfloat, "%lf", &x);
In C++, you might instead do something like this:
// REFERENCE: http://www.codeguru.com/forum/showthread.php?t=231054
include <string>
#include <sstream>
#include <iostream>
template <class T>
bool from_string(T& t,
const std::string& s,
std::ios_base& (*f)(std::ios_base&))
{
std::istringstream iss(s);
return !(iss >> f >> t).fail();
}
int main()
{
int i;
float f;
// the third parameter of from_string() should be
// one of std::hex, std::dec or std::oct
if(from_string<int>(i, std::string("ff"), std::hex))
{
std::cout << i << std::endl;
}
else
{
std::cout << "from_string failed" << std::endl;
}
if(from_string<float>(f, std::string("123.456"), std::dec))
{
std::cout << f << std::endl;
}
else
{
std::cout << "from_string failed" << std::endl;
}
return 0;
}
Personally, though, I'd recommend this:
http://bytes.com/topic/c/answers/137731-convert-string-float
There are two ways. C gives you strtod which converts between a char
array and double:
// C-ish:
input2 = strtod(input.c_str(), NULL);
The C++ streams provide nice conversions to and from a variety of
types. The way to use strings with streams is to use a stringstream:
// C++ streams:
double input2;
istringstream in(input);
input >> input2;
We can define a stringTo() function,
#include <string>
#include <sstream>
template <typename T>
T stringTo(const std::string& s) {
T x;
std::istringstream in(s);
in >> x;
return x;
}
Then, use it like
std::cout << stringTo<double>("-3.1e3") << " " << stringTo<int>("4");