这是用Visual Studio 2015编写的C ++代码。如下所示,
LPSTR *endPtr;
string strDouble = "0.03456";
double valDouble = strtod(strDouble.c_str(), &endPtr);
现在 valDouble 中的输出为“ 0.0345555566”,类似这样。
我希望 valDouble 中的值正好是“ 0.03456”。
基本上,“ 0.0345555566”的值需要四舍五入为“ 0.03456”。
有没有一种方法可以实现?
顺便说一句, strDouble 中的值一直在变化。因此,不可能将精度设置为5或类似的值。以下是 strDouble 的几个示例。
string strDouble = "0.1889";
string strDouble = "0.00883342";
string strDouble = "0.2111907";
string strDouble = "3.0045";
string strDouble = "1.45";
答案 0 :(得分:1)
我希望valDouble中的值恰好是“ 0.03456”。
这是不可能的,除非您针对一个其双浮点表示形式可以表示该数字的系统。
您的CPU可能使用的普遍存在的IEEE 754 binary64标准中没有0.03456的表示形式。最接近的可表示数字是3.45600000000000004418687638008E-2。无论您使用strtod
,stod
还是字符流来转换字符串,这就是您应该获得的数字。
有没有一种方法可以实现?
要在浮点不能表示该数字的系统上精确表示0.03456,必须使用整数表示该数字。您可以使用整数来实现任意精度的算术,定点算术或十进制浮点数。
基本上,值...需要四舍五入为“ 0.03456”。
将非精确浮点数转换为字符串时,可以舍入输出:
std::cout << std::setprecision(4) << 0.03456;
顺便说一句,strDouble中的值一直在变化。因此,不可能将精度设置为5或类似的水平。
然后,您必须记录输入字符串中的有效位数,以便在输出中使用相同的精度。
这是用于此目的的示例函数:
template<class Range>
auto get_precision(const Range& r)
{
auto is_significant = [](auto c) {
return std::isdigit(c) && c != '0';
};
auto first = std::find_if(std:: begin(r), std:: end(r), is_significant);
auto last = std::find_if(std::rbegin(r), std::rend(r), is_significant).base();
return std::count_if(first, last, [](auto c) {
return std::isdigit(c);
});
}
// demo
std::cout << get_precision("0.03456"); // 4
答案 1 :(得分:0)
假设您希望小数点后的位数为小数点后的总位数的一部分,则可以执行以下操作
n
d
50%
个小数位,可以使用一个古老的技巧 double d_new = round(d * pow(10.0, 5)) / pow(10.0, 5)
。假设精度达到5位数字。
注意:与其他答案不同,这里您将舍入原始十进制数。不只是将四舍五入的小数点打印到stdout。
示例:
#include<stdio.h>
#include<cmath>
int main(){
double a = 0.0345555566;
double b = 0.00883342;
double c = 0.2111907;
double a_new = round(a * pow(10.0, 5)) / pow(10.0, 5);
double b_new = round(b * pow(10.0, 4)) / pow(10.0, 4);
double c_new = round(c * pow(10.0, 3)) / pow(10.0, 3);
printf("%.10f\n", a_new);
printf("%.10f\n", b_new);
printf("%.10f\n", c_new);
}
查看50%的精度
结果:
0.0345600000
0.0088000000
0.2110000000
答案 2 :(得分:-1)
使用字符串流代替strtod:
#include <iostream>
#include <sstream>
double convert(std::string string) {
std::stringstream s(string);
double ret = 0;
s >> ret;
return ret;
}
int main() {
std::cerr << convert("0.03456") << std::endl;
std::cerr << convert("0.1889") << std::endl;
std::cerr << convert("0.00883342") << std::endl;
std::cerr << convert("0.2111907") << std::endl;
std::cerr << convert("3.0045") << std::endl;
std::cerr << convert("1.45") << std::endl;
return 0;
}
在我的系统上,这给出了:
0.03456
0.1889
0.00883342
0.211191
3.0045
1.45
正如一些评论中指出的那样,并非所有数字都可以用双精度表示。但是您列出的大多数都可以。