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
私は思った以上のことをしましたそれはそのようになります。
私は固定、setwとてSetPrecisionは相反する属性であると思います。彼らの関係は何ですか? – katang
@katang setwはフィールドの幅を固定します。 Setw(10)。 "0000000000"のようなことをするでしょう。配列の表示を整えるのに最適です。浮動小数点の扱い方を決定する固定/固定ではありません。 setprecision(2)+ setw(7)で固定すると、常に2つの数値精度で価格をうまく表示できます。構文はかなり醜いです。 boost :: formatをチェックすることができます。または外部lirary SafeFormat、Smft、fastformatなど – Gibet