2

ファイルから float 値を取得して、プログラムで使用しようとしています。次のフォーラムを使用して、プログラム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

float標準ストリームの浮動小数点の精度が低い可能性があるため、 with を出力するときに少数の小数しか表示されませんstd::coutstd::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

何も切り捨てられていません。double;を切り捨てることはできません。常に同じビット数と同じフォーマットを持ちます。ただし、デフォルトの精度 (6) とデフォルトの形式を使用して出力しています。これは常に有効桁数 6 桁を出力し、それ以上は出力しません。

ここには 2 つの問題があります。1 つ目は簡単です。必要な形式と精度は? 次の 3 つの形式があります。デフォルト (値に応じて固定または科学のいずれかを使用し、精度が有効桁数の最大数を表す)、固定、または科学的 (精度が後の桁数を表す)小数)。したがって、精度が 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()は、目的の形式で出力されます。

より一般的には、機械浮動小数点がどのように機能するかを理解していますか? double に格納されている実際の値は、ファイルに表示される値と異なります。ファイルに表示される値は、通常の double 形式では表現できないためです。入力した桁数については、同じ桁数を出力した場合、または 1 つまたは 2 つ多い桁数を出力した場合でも、違いは見られないはずですが、非常に多くの桁数 (たとえば約 17) を出力した場合は可能です。

于 2013-08-08T09:15:19.377 に答える
0

これは の精度の問題coutです。比較をテストしてみてください。

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

以下のコードを使用すると、いくつかの改善が得られます。

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

詳細については、以下の 2 つのリンクを参照してください。
http://www.cplusplus.com/reference/ios/ios_base/precision/
http://www.cplusplus.com/reference/iomanip/setprecision/

C++ でのコーディングをお楽しみください。;-)

于 2013-08-08T08:55:29.867 に答える