2

我正在尝试从文件中获取浮点值以在我的程序中使用它们。我使用下面的论坛来构建程序Read file line by line
但是通过这样做获得的值似乎在最后被截断。

我的代码

#include <iostream>
#include <cstring>
#include <sstream>
#include <fstream>
using namespace std;

int main()
{

ifstream file;
file.open("test_file.ssv");
string line;
while(file.good() && (getline(file, line)))
{
    istringstream iss(line);
    double a, b, c;
    iss >> a >> b >>c ;
    cout << a <<endl;
}
file.close();
return (0);
}

我获得的输出是

9292.31
32432.2

虽然我的文件有以下数据

9292.3123 4234.66 342.25423
32432.2423 3423.656 341.67841

有什么改进的建议吗?

4

4 回答 4

2

您的标准流可能具有较低的浮点精度,因此在输出 a floatwith时您只能看到几个小数std::cout。用于std::ios_base::precision增加精度并查看std:: ios::floatfield用于输出固定或科学精度,例如:

// modify precision
#include <iostream>     // std::cout, std::ios

    int main () {
      double f = 3.14159;
      std::cout.unsetf ( std::ios::floatfield );                // floatfield not set
      std::cout.precision(5);
      std::cout << f << '\n';
      std::cout.precision(10);
      std::cout << f << '\n';
      std::cout.setf( std::ios::fixed, std:: ios::floatfield ); // floatfield set to fixed
      std::cout << f << '\n';
      return 0;
    }

输出:

3.1416 3.14159 3.1415900000

于 2013-08-08T08:47:06.623 回答
0

使用下面的代码会有所改进。

std::cout << std::setprecision(10) << a << std::endl;

更多信息请参考以下两个链接:
http ://www.cplusplus.com/reference/ios/ios_base/precision/
http://www.cplusplus.com/reference/iomanip/setprecision/

使用 C++ 进行愉快的编码。;-)

于 2013-08-08T08:55:29.867 回答
0

这是精度的问题cout。尝试测试比较:

cout << "Stand.: " << a << "  Prec.: " << fixed << setprecision(10) << a << endl;
于 2013-08-08T08:46:31.497 回答
0

没有任何内容被截断。你不能截断double; 它始终具有相同的位数和相同的格式。但是您使用默认精度 (6) 和默认格式输出,它将始终输出 6 个有效数字,仅此而已。

这里有两个问题。第一个很简单:你想要什么格式和精度?有三种可能的格式:默认(将使用固定或科学,具体取决于值,并且精度表示有效数字的最大数量)、固定或科学(其中精度表示后面的位数小数)。因此,根据格式,精度为 6,您的第一个值将是:

default:    9292.31
fixed:      9292.312300
scientific: 9.292312E03

对于您显示的值,固定似乎最合适;但是如果你有非常小的值,它会显示更少的数字,而对于非常大的值,你可以获得一些很长的字符串。

处理这个问题的常用方法是为值所代表的任何内容定义一个操纵器;在这种情况下,我将直接调用它 values,因为我不知道有关您的应用程序的任何更精确的信息,但您可能应该找到一个更有意义的名称:

class value
{
    mutable std::ostream* myOwner;
    mutable std::ios_base::fmtflags myFlags;
    mutable int myPrecision;
    void capture( std::ostream& owner )
    {
        if ( myOwner == NULL ) {
            myOwner = &owner;
            myFlags = myOwner->fmtflags();
            myPrecision= myOwner->precision();
        }
    }
public:
    value() : myOwner( NULL ) {}
    ~value()
    {
        if ( myOwner != NULL ) {
            myOwner->flags( myFlags );
            myOwner->precision( myPrecision );
        }
    }
    friend std::ostream& operator<<( std::ostream& dest, value const& manip )
    {
        manip.capture( dest );
        dest.setf( std::ios_base::fixed, std::ios_base::floatfield );
        dest.precision( 6 );
    }
};

这也将恢复完整表达式末尾的格式化状态(因为它只能用作临时);这通常是一个好主意,因为它可以防止以后代码中出现意外。如果您正在做任何重要的输出,您将创建一个用于保存和恢复的基类,并从中派生您的实际操纵器。

一旦你有了这个,你可以写:

std::cout << value() << a << " " << b << " " << c << std::endl;

语句中后面的所有值value()都将以所需的格式输出。

更一般地说,您了解机器浮点的工作原理吗?存储在双精度中的实际值不会是您在文件中看到的值,因为您在文件中看到的值不能以通常的双精度格式表示。对于您输入的位数,如果您输出相同的位数,或者甚至更多位数,您应该不会看到任何差异,但如果您输出的位数非常多(比如大约 17 个),则可以。

于 2013-08-08T09:15:19.377 回答