8つの符号なし文字がx1,x2,...x8
あり、計算したいとします:
abs((x1 + x2 + x3 + x4) - (x5 + x6 + x7 + x8)) / 4
大きなオーバーフローまたはアンダーフロー エラーを発生させずに、最も正確な結果を保証する最善の方法は何でしょうか?
これをテンプレート クラスで使用しているため、符号なしの値を符号付きの値に変換することはできません。
8つの符号なし文字がx1,x2,...x8
あり、計算したいとします:
abs((x1 + x2 + x3 + x4) - (x5 + x6 + x7 + x8)) / 4
大きなオーバーフローまたはアンダーフロー エラーを発生させずに、最も正確な結果を保証する最善の方法は何でしょうか?
これをテンプレート クラスで使用しているため、符号なしの値を符号付きの値に変換することはできません。
以上のoperator +
場合のみ機能しint
ます。char
したがって、型(int より小さい) のオブジェクトで使用すると、これらの値は操作が行われる前に自動的に int に変換されます。
したがって
abs((x1 + x2 + x3 + x4) - (x5 + x6 + x7 + x8)) / 4
コンパイラによって次のように変換されます。
abs((static_cast<int>(x1) + static_cast<int>(x2) + static_cast<int>(x3) + static_cast<int>(x4)) -
(static_cast<int>(x5) + static_cast<int>(x6) + static_cast<int>(x7) + static_cast<int>(x8))) / 4
したがって、大量の文字を追加しない限り、オーバーフローする可能性は低くなります。
結果を に戻す際に問題がありunsigned char
ます。式の結果が負の場合、値を正にする変換が行われます (ただし、明確に定義されています)。
メタ関数を使用して、計算で使用する中間データ型を伝えたいようです。
template <class T>
struct arithmetic_type
{
typedef std::int64_t type;
};
template <>
struct arithmetic_type<float>
{
typedef double type;
};
template <>
struct arithmetic_type<double>
{
typedef double type;
};
template <>
struct arithmetic_type<std::uint64_t>
{
typedef std::uint64_t type;
};
typedef typename arithmetic_type<T>::type ar_type;
abs(((ar_type)x1 + x2 + x3 + x4) - ((ar_type)x5 + x6 + x7 + x8)) / 4;
もちろん、必要に応じて専門化を微調整したり、追加/削除したりできますが、これで正しいアイデアが得られるはずです。