2016-12-19 15 views
5

私はC++(ストリームを使用して)で小数点の後に最大4桁を印刷しようとしています。したがって、小数点以下4桁を必要としない場合は、実際に必要な小数点以下の桁数だけを使用します。最大4小数点を印刷

例:

1.12345 -> 1.1234 
1.0  -> 1 
1.12  -> 1.12 
1.12345789 -> 1.1234 
123.123 -> 123.123 
123.123456 -> 123.1234 

Iはstd::setprecision(4)を試みたが、それは、有効桁数を設定し、テストケースに失敗:

123.123456 gives 123.1 

Iもstd::setprecision(4)と共にstd::fixedを与える試みたが、それは、A与えます必要でない場合でも小数点以下の固定桁数:

1.0 gives 1.0000 

std::defaultfloatは私が必要としていて固定でも指数関数的でもないようです。しかし、小数点以下の桁数は適切に表示されておらず、有効桁数のオプションしかありません。

+4

これは、カスタムコードを必要とし、印刷する値のBCDまたは文字列表現を処理します。浮動小数点数の基礎となる表現はバイナリであるため、必ずしも123.123の正確なバイナリ表現であるとは限りません。十分な小数点以下の桁数を示していれば、 'double x = 123.123; cout << x'は '123.1230000001'のようなものを出力できます。したがって、私は4つの小数点以下の桁を持つ文字列にdoubleを変換し、文字列を返す前に、小数点以下の後にゼロを削除する関数を書くことを提案したいと思います。 – Simon

+0

あなたの例は問題の説明と一致しません。これらの例を見ると、末尾に0を付けずに4小数点以下を望むようになります。確かにちょうど4小数と同じではありません。さらに、IEEE浮動小数点値の表現の性質を考えると、Simonが指摘しているように、*「必要な数字」*が意味すると思われるもののより良い仕様を生成する必要があります。 – IInspectable

+2

[浮動小数点演算について各コンピュータ科学者が知っておくべきこと](https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html)が必要です。 – IInspectable

答えて

4

std::stringstreamstd::stringを使用してこれを行うことができます。私たちがcoutに送信した場合のように、doubleをストリームにフォーマットします。次にストリームから取得した文字列を調べて、末尾にゼロがあるかどうかを調べます。もし私たちがそれらを取り除くならば。一度それを行うと、小数点だけ残っているかどうかを確認します。あなたはこのようなものを使用することができますrunning exampleに作ら

int main() 
{ 
    double values[] = { 1.12345, 1.0, 1.12, 1.12345789, 123.123, 123.123456, 123456789, 123.001 }; 
    std::vector<std::string> converted; 
    for (auto e : values) 
    { 
     std::stringstream ss; 
     ss << std::fixed << std::setprecision(4) << e; 
     std::string value(ss.str()); 
     if (value.find(".") != std::string::npos) 
     { 
      // erase trailing zeros 
      while (value.back() == '0') 
       value.erase(value.end() - 1); 
      // if we are left with a . at the end then get rid of it 
      if (value.back() == '.') 
       value.erase(value.end() - 1); 
      converted.push_back(value); 
     } 
     else 
      converted.push_back(value); 
    } 
    for (const auto& e : converted) 
     std::cout << e << "\n"; 
} 

はゼロとポイントを削除するには、カスタム・ロジックと一緒にhereからの回答を使用して

1.1235 
1 
1.12 
1.1235 
123.123 
123.1235 
123456789 
123.001 
1

を与える:

#include <iostream> 
#include <iomanip> 
#include <sstream> 
#include <string> 
#include <vector> 
#include <iterator> 
#include <algorithm> 

std::string remove_zeros(std::string numberstring) 
{ 
    auto it = numberstring.end() - 1; 
    while(*it == '0') { 
     numberstring.erase(it); 
     it = numberstring.end() - 1; 
    } 
    if(*it == '.') numberstring.erase(it); 
    return numberstring; 
} 

std::string convert(float number) 
{ 
    std::stringstream ss{}; 
    ss << std::setprecision(4) << std::fixed << std::showpoint << number; 
    std::string numberstring{ss.str()}; 
    return remove_zeros(numberstring); 
} 

int main() 
{ 
    const float values[]{1.12345, 1.0, 1.12, 1.12345789, 147323.123, 123.123456}; 
    for(auto i : values) 
     std::cout << convert(i) << '\n'; 
} 

は:

1.1235 
1 
1.12 
1.1235 
147323.125 
123.1235 
関連する問題