将double插入stringstream时避免舍入

时间:2016-06-21 13:05:07

标签: c++ floating-point double rounding

我正在使用此函数将双f转换为小数点后带p位的字符串。

static std::string doubleToString(double f, int p)
{
        std::stringstream ss;
        ss << std::fixed << std::setprecision(p) << f;
        std::string s = ss.str();                                   
        s.erase(s.find_last_not_of('0') + 1, std::string::npos);    
        return (s[s.size()-1] == '.') ? s.substr(0, s.size()-1) : s;
}

末尾的重复0被删除。例如,1.23000获取1.23

输入:

double test1 = 1;
double test2 = 1.12345678;
double test3 = 1.123456789010;

std::cout << doubleToString(test1, 8) << " " << doubleToString(test2, 8) << " " << doubleToString(test3, 8);

输出

1 1.12345678 1.12345679

正如您所看到的,test1test2打印得很好。然而,test3在第8位后变为圆形。我想避免这种情况并“删除”其余部分,以便:doubleToString(1.123456789010, 8)返回1.12345678

最有效的方法是什么?

2 个答案:

答案 0 :(得分:1)

您可以尝试:

doubleToString( ( test3 - ( 0.5 / ( pow( 10, 8 ) ) ) ), 8 )

这不是一个明确的解决方案,但应该做你想做的事。

编辑: 它只是从您的数字中减去0.000000005,所以它没有四舍五入。您可以将它添加到您的函数中,它将使用每个数字执行此操作:

static std::string doubleToString(double f, int p)
{
    std::stringstream ss;
    ss << std::fixed << std::setprecision(p) << (f - (0.5 / (pow(10, p))));
    std::string s = ss.str();                                   
    s.erase(s.find_last_not_of('0') + 1, std::string::npos);    
    return (s[s.size()-1] == '.') ? s.substr(0, s.size()-1) : s;
}

答案 1 :(得分:1)

对您的功能进行一些小修改即可完成任务;只需在流中添加一些额外的数字,然后在转换后将其剥离。您需要允许某些舍入,因为二进制值可能略小于您期望的十进制值。在我的下面的代码中,我将字符串转换限制为14位数,这大约是IEEE在1.0和10.0之间的双倍最大值;如果您希望值大于此值,则需要调整算法,因为小数点后的准确位数将会下降。

<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix">
        <value>/WEB-INF/includes/</value>
    </property>
    <property name="suffix">
        <value>.jsp</value>
    </property>
</bean>

http://ideone.com/xGoDiH看到它的实际效果。