2

我正在使用ofstream. 99% 的浮点数的精度为小数点后 1-2 位,因此简单地使用fileOut.precision(3)就足以强制实现正确的精度。

不时地,浮点数将具有极低的值,因此将以科学记数法输出1e-007。在这种情况下,我最好喜欢0.

这里的很多答案都建议使用类似于 to的东西fileOut.setf(std::ios::fixed, std::ios::floatfield);来防止这种情况,但这会使每个字段都输出,0.000而不管它是否需要那么多数字。

我想要的是所有花车都能正常运行并且不显示科学记数法。

有没有办法做到这一点,或者我必须创建一个简单的函数来检查一个 numebr 是否低于,比如说,0.001如果是的话,将它设置为 0?

更新:

我现在使用以下代码来环绕任何浮点数,它并不理想但可以工作。

float _RoundToZero(float in, int precision = 2)
{
  return in <= (1 / powf(10,precision)) ? 0.0 : in;
}
4

2 回答 2

0

iostream 抱歉,用and 是不可能实现的printf。唯一的选择是:

  • 实现您自己的浮点格式化例程以进行正确的舍入。
  • 将浮点数格式化为字符串并修剪零。
  • 如果该值小于阈值,则将其四舍五入为零。

第一个很复杂,最后一个不准确(不能精确地表示 10 -n二进制浮点数)。

所有这些都可以通过覆盖 numput 方面来实现,这将允许您让格式化代码像以前一样干净。

这是最后一个选项的实现:

#include <iostream>
#include <locale>
#include <math.h>
using namespace std;

class my_put : public std::num_put<char> {
    iter_type do_put (iter_type out, ios_base& str, char_type fill, double val) const
    {
        streamsize prec = str.precision();
        if((str.flags() & ios_base::floatfield) == ios_base::fixed && fabs(val)*2 <= pow(10.0, -(int)prec))
            str.precision(0);
        out = std::num_put<char>::do_put(out, str, fill, val);
        str.precision(prec);
        return out;
    }
};

int main()
{
    double a[] = {123, 0, 0.001, 0.0001 };
    cout.imbue(locale(cout.getloc(), new my_put));
    cout.precision(3);
    cout.setf(ios_base::fixed, ios_base::floatfield);
    for(int i = 0; i < 4; ++i)
        cout << a[i] << '\n';
}

在此处查看输出:http: //ideone.com/qaV0w

请注意,边界情况 (0.0005) 的正确性取决于下划线浮点格式和实现。

于 2012-06-20T13:37:49.590 回答
0

考虑将乘以 100 的值打印为整数(四舍五入以确保准确性)。这样,尽管有时您会得到尾随零,但您永远不必打印小数位,这将浪费每个值 1 个字符。

或者,将浮点数写入二进制。由于所有浮点数都具有相同的大小(4 个字节),因此您可以保留原始的所有精度,而不必担心尾随零,您的文件大小是非常可预测的,并且您不必浪费空间来分隔值。100 个值占用 400 个字节。在文本格式中,一个值至少需要 2 个字节(数字 + 字段分隔符)和最大格式允许的任何内容(包括小数点)加上分隔符。在这种格式中,4 个字节可以获得 2 个有效数字的精度,而不是浮点数的 5 或 6。

于 2012-06-20T13:39:25.720 回答