在 C++ 写入文件时意外四舍五入双类型

bre*_*ntf 4 c++ rounding ofstream

我正在开发一个 C++ 程序,其中包含许多 double 类型的数字(数百万和数十亿的值,小数点右侧只有几个位置)。我正在对这些数字进行计算,然后将结果打印到文本/CSV 文件中。我注意到在文本文件中,我的所有数字似乎都四舍五入(到六位数)。因此,值 13,169,911 在我的输出文件中显示为 13,169,900。

这种四舍五入只发生在印刷品上吗?为了获得变量中的完整位数,我是否只需要在写入文件时指定一些内容?我在下面包含了我写入文件代码的示例:

void PrintPropFinance(vector<PropFinance>& PF, int NumProps, int Iterations, int ForecastLength, 
          string CurDeal, string ModelRunID, string ScenName, Assumptions& Ass) {

string filename;
ofstream OutFile;
ostringstream s1;

s1 << BASEPATH << "Output/" << CurDeal << "_" << ModelRunID << "_" << 
            ScenName << "_PropFinance" << ".csv";
filename = s1.str();

OutFile.open(filename);

// Put in the column headers first
OutFile << "PropID" << "," 
        << "Item" << ","
        << "StartDate" << ","
        << "NumOfPeriod" << ","
        << "Result" << ","
        << "Isap" << ","
        << "CurLoanBal" << ","

for (int i=1; i<=NumProps; ++i) {
    // Populate the single-vector variables
    OutFile << PF[i].PropID << "," 
            << PF[i].Item << ","
            << PF[i].StartDate << ","
            << PF[i].NumOfPeriod << ","
            << PF[i].Result << ","
            << PF[i].Isap << ","
            << PF[i].CurLoanBal << ","
                                    << endl;
}
OutFile.close();
}

// Prop finance class definition
class PropFinance {
public:
    string PropID;
    int Item;
    string StartDate;

    int NumOfPeriod;
    string Isap;
    double CurLoanBal;
}
Run Code Online (Sandbox Code Playgroud)

das*_*ght 5

问题可能与输出流为doubles生成输出的方式有关:如果13169911以“科学记数法”打印,它看起来像1.31699E7. Excel 会很好地读取这个符号,但会为它没有“看到”的数字加上零,使数字看起来像13,169,900.

要解决此问题,请fixed在输出时添加操纵器double以确保打印所有数字:

OutFile << PF[i].PropID << "," 
        << PF[i].Item << ","
        << PF[i].StartDate << ","
        << PF[i].NumOfPeriod << ","
        << fixed << PF[i].Result << ","
        << PF[i].Isap << ","
        << fixed << PF[i].CurLoanBal << ","
        << endl;
Run Code Online (Sandbox Code Playgroud)


Ben*_*ers 5

您需要使用std::setprecision来提高流的精度。默认情况下 aniostream只有 6 位精度。

尝试这个:

OutFile << std::setprecision(std::numeric_limits<long double>::digits10 << PF[i].CurLoanBal;
Run Code Online (Sandbox Code Playgroud)

请记住,这将影响流上的所有后续操作。老实说,这可能就是您想要的!

作为std::setprecision和之间的比较std::fixed,该程序:

#include <iostream>
#include <iomanip>
#include <cmath>
#include <limits>
int main()
{
    const long double test_value = 13169911.7777777;
    std::cout << "default precision (6):              " << test_value << '\n'
              << "std::fixed:                         " << std::fixed << test_value << '\n'
              << "std::precision(10):                 " << std::defaultfloat << std::setprecision(10) << test_value << '\n'
              << "std::precision(10) & std::fixed:    " << std::fixed        << std::setprecision(10) << test_value << '\n'
              << "max precision:                      " << std::defaultfloat << std::setprecision(std::numeric_limits<long double>::digits10) << test_value << '\n'
              << "max precision & std::fixed:         " << std::fixed        << std::setprecision(std::numeric_limits<long double>::digits10) << test_value << '\n'
    ;
}
Run Code Online (Sandbox Code Playgroud)

产生以下输出:

default precision (6):              1.31699e+007
std::fixed:                         13169911.777778
std::precision(10):                 13169911.78
std::precision(10) & std::fixed:    13169911.7777777000
max precision:                      13169911.7777777
max precision & std::fixed:         13169911.777777700000000
Run Code Online (Sandbox Code Playgroud)

所以我认为你可能想要std::setprecision而不是std::fixed。尽管我想无论如何你都只会有两位小数,所以也许这并不重要。

在这里阅读更多内容:http ://en.cppreference.com/w/cpp/io/manip/set precision