如何防止数字出现在科学记数中

时间:2016-02-07 19:40:35

标签: c++ scientific-notation

我们有一个StreamBuffer课程,我们尚未执行std::fixed操作,我正在尝试阻止数字出现在科学记数法中。用我的下面的代码,一些数字以科学记数显示。我们希望避免进行任何分配,这是因为性能原因我们实施StreamBuffer类的原因。

以下是代码:

T value = 0;

template<typename U> void process(U& buf, DataOption holder) const {
    if (holder == DataOption::TYPES) {
        switch (type_) {
        case teck::PROC_FLOAT:
            buf << "{\"float\":" << value << "}";
            break;
        case teck::PROC_DOUBLE:
            buf << "{\"double\":" << value << "}";
            break;
        default:
            buf << "{\"" << type_ << "\":" << value << "}";
        }
    }
}

这就是它被调用的方式:

void HolderProcess::dump(std::ostream& os, DataOption holder) const 
{
    process<std::ostream>(os, holder);
}

void HolderProcess::dump(StreamBuffer& buffer, DataOption holder) const
{
    process<StreamBuffer>(buffer, holder);
}

我尝试使用如下所示,我收到错误,据我所知,我们无法在std::fixed课程中使用StreamBuffer

case teck::PROC_DOUBLE:
    buf << "{\"double\":" << std::fixed << value << "}";

std::fixed的替代方法是什么,我可以在这里使用,根本不做任何分配。我正在考虑将数字转换为字符串,然后在其上应用std::fixed,但这也会做一些分配,我想避免这种情况。

执行此操作的最佳方式是效率高,并且不进行任何分配?我有一个下面的解决方案,但它会做一些分配,因为它使用字符串。我可以从上面的代码中调用以下方法。

template <typename T> string str(T number)
   {
       std::ostringstream ss;
       ss << std::fixed << number;
       return ss.str();
   }

还有其他优化和有效的方法吗?

3 个答案:

答案 0 :(得分:8)

StreamBuffer类必须从std :: ios_base(或其某些派生词,如std :: ostream)继承您的预期行为。 std::fixed只能与STL中可用的衍生实现一起使用。

此外,如果您有权访问std :: ios_base,您还可以使用std::ios_base::precision

如果您遇到无法更新类的情况,那么最常用和传统的方法是通过缩放浮点数。为了减少重复,请查看已经回答的问题here。例如,对于第三度精度,我将所有'value'实例替换为:

select 
     id,modelname 
from 
    res_reservations 
where 
    resnumber!="9915" and 
    datestart > now() and 
   (datestart BETWEEN "2016-02-13 09:00:00" AND "2016-02-15 09:00:00") or
   (dateend BETWEEN "2016-02-13 09:00:00" AND "2016-02-15 09:00:00") or
   (datestart < "2016-02-13 09:00:00" AND  dateend >"2016-02-15 09:00:00")
order by id ASC

更好地理解提问者的要求。我已经意识到上述内容不适用于指数。为了解决这个问题,我建议做以下事情:

// case teck::PROC_FLOAT:
static_cast<float>( static_cast<int>(value*1000) ) / 1000
// case techk::PROC_DOUBLE:
static_cast<double>( static_cast<long long>(value*1000) ) / 1000

然而,这肯定会分配更多的内存。

答案 1 :(得分:6)

只需使用snprintf:

#include <cstdio>
#include <limits>
#include <iostream>

int main() {
    double value = 0.1234567890123456789;
    const int Precision = std::numeric_limits<double>::digits10;
    const std::size_t StringBufferSize = Precision + 3; // sign, dot and terminating zero.
    char str[StringBufferSize];
    std::snprintf(str, StringBufferSize - 1, "%.*f", Precision, value);
    str[StringBufferSize - 1] = 0;
    // buf << "{\"double\":" << str << "}";
    std::cout << str << '\n';
}

答案 2 :(得分:0)

在我看来,也许你应该尝试CppFormat。有一些示例说明如何使用它来格式化here