2017-05-02 13 views
0

私はテーブルを作成することを目標と固定精度の倍精度を所定の長さにフォーマットするにはどうすればよいですか?

std::cout << " " << std::setw(7) << std::setprecision(5) << Value ; 

のような形式の出力を使用しています。テーブルには、しかし、次のように表示されます

 0 6.0303 16.052 40.523  100 40.557 16.167 6.7314 1.8967  0 
    0 4.5593 13.16 25.342 41.927 25.354 13.312 4.9988 1.9527  0 
    0 3.0952 6.6864 13.531 17.01 13.544 6.7291 3.466 0.91553  0 
    0 1.1353 3.466 5.0842 7.3242 5.0842 3.4981 1.2207 0.56076  0 
    0 0.54474 0.95825 2.153 2.1179 2.153 0.95825 0.5928 0.10681  0 
    0 0.085449 0.38452 0.45166 0.78392 0.45166 0.38452 0.085449 0.048065  0 
    0 0.032043 0.042725 0.15221 0.11444 0.15221 0.042725 0.032043  0  0 
    0  0  0  0  0  0  0  0  0  0 

小数点以下一桁目がゼロの場合、displaydの長さは1つの文字長いように見えます。どうすればそれを避けることができますか?

答えて

0

hm。だから私はすべてのエッジケースについて考えた後にこれをしたかったのです。私はいくつかの権利を扱っていないと確信しています、そして、これはCでもっときれいだと思いますが、それは問題ないと思います。

あなたは何が起こっているのかを知っていれば、コメントで自由に編集できます。いくつかの警告を除き

:テストの下

これが道の上に設計され

、および方法。

携帯用ではありませんが、もう少し作業して作ることができます。

テスト/コーナーケースの追加行を入力に追加しました。

これは必要以上に多くの可能性がありますが、一般化することができます。または、それをよりよくするライブラリを使用してください。

#include <cmath>                     
#include <cstdint>                    
#include <iomanip>                    
#include <iostream>                    
#include <vector>                    

const std::vector<std::vector<double>> array = {             
    // OP's data.                     
    {0, 6.0303, 16.052, 40.523, 100, 40.557, 16.167, 6.7314, 1.8967, 0},       
    {0, 4.5593, 13.16, 25.342, 41.927, 25.354, 13.312, 4.9988, 1.9527, 0},      
    {0, 3.0952, 6.6864, 13.531, 17.01, 13.544, 6.7291, 3.466, 0.91553, 0},      
    {0, 1.1353, 3.466, 5.0842, 7.3242, 5.0842, 3.4981, 1.2207, 0.56076, 0},      
    {0, 0.54474, 0.95825, 2.153, 2.1179, 2.153, 0.95825, 0.5928, 0.10681, 0},     
    {0, 0.085449, 0.38452, 0.45166, 0.78392, 0.45166, 0.38452, 0.085449, 0.048065, 0},   
    {0, 0.032043, 0.042725, 0.15221, 0.11444, 0.15221, 0.042725, 0.032043, 0, 0},    
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0},                
    // My test data.                    
    {1e-7, 1.12031e-34, 1e-34, 1e-6, 1e33, 1e-8, 1.3123233e93, 1e32, 1.e99, 1.e100},    
    {-1e-7, -1.12031e-34, -1e-34, -1e-6, -1e33, -1e-8, -1.3123233e93, -1e32, -1.e99, -1.09e100}, 
};                        

// Warning: any widths under 7 cannot accurately print the double -1e+100...      
// (or many like it). There's just no way to express that any more tersely!      
constexpr uint8_t kWidth = 7;                 
// Most of these are really obvious but help make the code slightly cleaner.      
// "."                       
constexpr uint8_t kWidthTakenByDecimalSeparator = 1;            
// "-"                       
constexpr uint8_t kWidthTakenByNegativeSign = 1;             
// "e+" or "e-"                     
constexpr uint8_t kWidthOfExtraScientificNotationCharacters = 2;         
// On *MY* system, 1.0e-08 is always printed, not 1.0e-8. This basically handles     
// the leading 0 on the exponent. Tune accordingly (or find the right compiler     
// flags that give you the right number(s).              
constexpr uint8_t kMinimumWidthOfScientificNotationExponent = 2;         

int main() {                      
    // Store the original std::cout flags.               
    auto old_flags = std::cout.flags();               
    for (auto& row : array) {                  
    for (auto& value : row) {                 
     const double log10_value = log10(std::abs(value));           
     const uint8_t available_width = kWidth - (value < 0) * kWidthTakenByNegativeSign;   
     // Handle numbers greater than 10^kWidth or less than 10^-kWidth in      
     // scientific notation.                 
     const bool use_scientific_notation =              
      value != 0 &&                   
      (log10_value < -1.0 * available_width + kWidthTakenByDecimalSeparator +    
          kWidthTakenByNegativeSign ||          
      log10_value > available_width);              
     std::cout << ' ' << std::setw(kWidth);              
     if (use_scientific_notation) {                
     const double log10log10_value = log10(log10_value);          
     const uint8_t num_digits_in_exponent_of_scientific_notation =       
      std::max(kMinimumWidthOfScientificNotationExponent,         
        static_cast<uint8_t>(log10log10_value));         
     const uint8_t num_digits_desired_after_decimal_scientific =        
      std::max(1.0, log10log10_value);              
     uint8_t potential_new_precision =              
      available_width - num_digits_in_exponent_of_scientific_notation -     
      kMinimumWidthOfScientificNotationExponent -           
      kWidthTakenByDecimalSeparator -              
      num_digits_desired_after_decimal_scientific;           
     // Lazy underflow checking. Needed?              
     if (potential_new_precision > available_width) {           
      potential_new_precision = 0;               
     }                  
     std::cout << std::scientific            
        << std::setprecision(potential_new_precision);     
     } else {                 
     // We take the max with 1.0 to compensate for the leading 0 in decimals. 
     // If your system doesn't put a leading zero there, remove it.   
     const uint8_t number_of_digits_before_decimal_fixed =     
      std::max(log10_value + 1.0, 1.0);         
     const uint8_t number_of_digits_desired_after_decimal_fixed =    
      available_width - kWidthTakenByDecimalSeparator -     
      number_of_digits_before_decimal_fixed;        
     // Fixed width decimals -- this means that the code      
     // std::cout << std::precision(n)          
     // tells the stream to use n digits *after the decimal*.     
     std::cout << std::fixed             
        << std::setprecision(           
         number_of_digits_desired_after_decimal_fixed);   
     }                   
     std::cout << value;              
    }                   
    std::cout << '\n';               
    }                    
    // Reset the flags to their old value, and flush the output buffer.   
    std::cout.flush();                
    std::cout.flags(old_flags);             
}  

と楽しいもの:kWidth = 7と

出力例:kWidthと

0.00000 6.03030 16.0520 40.5230 100.000 40.5570 16.1670 6.73140 1.89670 0.00000 
0.00000 4.55930 13.1600 25.3420 41.9270 25.3540 13.3120 4.99880 1.95270 0.00000 
0.00000 3.09520 6.68640 13.5310 17.0100 13.5440 6.72910 3.46600 0.91553 0.00000 
0.00000 1.13530 3.46600 5.08420 7.32420 5.08420 3.49810 1.22070 0.56076 0.00000 
0.00000 0.54474 0.95825 2.15300 2.11790 2.15300 0.95825 0.59280 0.10681 0.00000 
0.00000 0.08545 0.38452 0.45166 0.78392 0.45166 0.38452 0.08545 0.04806 0.00000 
0.00000 0.03204 0.04272 0.15221 0.11444 0.15221 0.04272 0.03204 0.00000 0.00000 
0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 
1.0e-07 1.1e-34 1.0e-34 1.0e-06 1.0e+33 1.0e-08 1.3e+93 1.0e+32 1.0e+99 1e+100 
-1e-07 -1e-34 -1e-34 -1e-06 -1e+33 -1e-08 -1e+93 -1e+32 -1e+99 -1e+100 

出力例= 10:

0.00000000 6.03030000 16.0520000 40.5230000 100.000000 40.5570000 16.1670000 6.73140000 1.89670000 0.00000000 
0.00000000 4.55930000 13.1600000 25.3420000 41.9270000 25.3540000 13.3120000 4.99880000 1.95270000 0.00000000 
0.00000000 3.09520000 6.68640000 13.5310000 17.0100000 13.5440000 6.72910000 3.46600000 0.91553000 0.00000000 
0.00000000 1.13530000 3.46600000 5.08420000 7.32420000 5.08420000 3.49810000 1.22070000 0.56076000 0.00000000 
0.00000000 0.54474000 0.95825000 2.15300000 2.11790000 2.15300000 0.95825000 0.59280000 0.10681000 0.00000000 
0.00000000 0.08544900 0.38452000 0.45166000 0.78392000 0.45166000 0.38452000 0.08544900 0.04806500 0.00000000 
0.00000000 0.03204300 0.04272500 0.15221000 0.11444000 0.15221000 0.04272500 0.03204300 0.00000000 0.00000000 
0.00000000 0.00000000 0.00000000 0.00000000 0.00000000 0.00000000 0.00000000 0.00000000 0.00000000 0.00000000 
0.00000010 1.1203e-34 1.0000e-34 0.00000100 1.0000e+33 0.00000001 1.3123e+93 1.0000e+32 1.0000e+99 1.000e+100 
-0.0000001 -1.120e-34 -1.000e-34 -0.0000010 -1.000e+33 -1.000e-08 -1.312e+93 -1.000e+32 -1.000e+99 -1.09e+100 

私は思った以上のことをしましたそれはそのようになります。

1

用途:

std::cout << std::fixed; 

デフォルトの動作は、「精度」に桁数を表示することです。 std :: fixedは、正確な桁数で表示されます。したがって、デフォルトでは5つの有効数字が表示されます。固定された5つの数字。たとえば

auto a = 2017.0; 

default = 2017 
fixed = 2017.00000 

auto b = 1e-10; 

default= 1e-10 

fixed = 0.00000 
+0

私は固定、setwとてSetPrecisionは相反する属性であると思います。彼らの関係は何ですか? – katang

+0

@katang setwはフィールドの幅を固定します。 Setw(10)。 "0000000000"のようなことをするでしょう。配列の表示を整えるのに最適です。浮動小数点の扱い方を決定する固定/固定ではありません。 setprecision(2)+ setw(7)で固定すると、常に2つの数値精度で価格をうまく表示できます。構文はかなり醜いです。 boost :: formatをチェックすることができます。または外部lirary SafeFormat、Smft、fastformatなど – Gibet

関連する問題