如何防止数字出现在科学记数法中
how to prevent numbers from showing up in scientific notations
我们有一个 StreamBuffer
class,其中我们还没有实现 std::fixed
操作,我试图防止数字以科学记数法出现。在我下面的代码中,一些数字以科学计数法显示。我们希望避免进行任何分配,因此出于性能原因,我们实施了 StreamBuffer
class。
代码如下:
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);
}
我尝试使用如下所示的方式,但出现错误,据此我明白我们不能在我的 StreamBuffer
class.
上使用 std::fixed
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();
}
还有其他优化高效的方法吗?
StreamBuffer class 必须继承自 std::ios_base(或它的某些衍生物,例如 std::ostream)以实现您的预期行为。 std::fixed 只能使用作为 STL 一部分的可用内容的派生实现。
此外,如果您可以访问 std::ios_base,您还可以使用 std::ios_base::precision。
如果您遇到无法更新 class 的情况,那么最常用和传统的方法是缩放浮点数。为了减少重复,请查看已回答的问题 here。例如,对于 3 级精度,我会将所有 'value' 个实例替换为:
// 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
更好地理解了提问者的需求。我已经意识到以上不适用于指数。为了解决这个问题,我建议执行以下操作:
case teck::PROC_FLOAT:
std::stringstream ss;
ss << std::fixed << value;
buf << "{\"float\":" << ss.str() << "}";
break;
但是,这肯定会分配更多内存。
只需使用 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';
}
我觉得也许你应该试试 CppFormat. There are some examples of how to use it for formatting here。
我们有一个 StreamBuffer
class,其中我们还没有实现 std::fixed
操作,我试图防止数字以科学记数法出现。在我下面的代码中,一些数字以科学计数法显示。我们希望避免进行任何分配,因此出于性能原因,我们实施了 StreamBuffer
class。
代码如下:
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);
}
我尝试使用如下所示的方式,但出现错误,据此我明白我们不能在我的 StreamBuffer
class.
std::fixed
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();
}
还有其他优化高效的方法吗?
StreamBuffer class 必须继承自 std::ios_base(或它的某些衍生物,例如 std::ostream)以实现您的预期行为。 std::fixed 只能使用作为 STL 一部分的可用内容的派生实现。
此外,如果您可以访问 std::ios_base,您还可以使用 std::ios_base::precision。
如果您遇到无法更新 class 的情况,那么最常用和传统的方法是缩放浮点数。为了减少重复,请查看已回答的问题 here。例如,对于 3 级精度,我会将所有 'value' 个实例替换为:
// 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
更好地理解了提问者的需求。我已经意识到以上不适用于指数。为了解决这个问题,我建议执行以下操作:
case teck::PROC_FLOAT:
std::stringstream ss;
ss << std::fixed << value;
buf << "{\"float\":" << ss.str() << "}";
break;
但是,这肯定会分配更多内存。
只需使用 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';
}
我觉得也许你应该试试 CppFormat. There are some examples of how to use it for formatting here。