私の質問は、すべての整数値が完全な二重表現を持つことが保証されているかどうかです。
「同じ」を出力する次のコードサンプルを検討してください。
// Example program
#include <iostream>
#include <string>
int main()
{
int a = 3;
int b = 4;
double d_a(a);
double d_b(b);
double int_sum = a + b;
double d_sum = d_a + d_b;
if (double(int_sum) == d_sum)
{
std::cout << "Same" << std::endl;
}
}
これは、アーキテクチャ、コンパイラ、a
およびb
のすべての値に当てはまることが保証されていますか? i
に変換された整数double
は、たとえばi.0000000000000
ではなく、常にi.000000000001
として表されますか?
私は他のいくつかの数字で試してみましたが、それは常に真実でしたが、これが偶然なのか、設計によるのかについては何も見つけることができませんでした。
注:これは、2つの整数を追加するため、 この質問 (言語は別として)とは異なります。
免責事項(Toby Speightが提案):IEEE 754表現は非常に一般的ですが、実装では言語の要件を満たす他の表現を使用することが許可されています。
Doubleはmantissa * 2^exponent
の形式で表されます。つまり、一部のビットはdoubleの整数以外の部分に使用されます。
bits range precision
float 32 1.5E-45 .. 3.4E38 7- 8 digits
double 64 5.0E-324 .. 1.7E308 15-16 digits
long double 80 1.9E-4951 .. 1.1E4932 19-20 digits
分数の部分は、ドットの後のすべての数字を削除する指数を使用して整数を表すためにも使用できます。
例えば。 2,9979・10 ^ 4 = 29979。
一般的なint
は通常32ビットなので、すべてのint
sをdoubleとして表すことができますが、64ビット整数の場合、これはもはや当てはまりません。より正確に(コメントでLThodeが述べているように):IEEE 754倍精度は、これを最大53ビット(仮数の52ビット+暗黙の先行1ビット)に対して保証できます。
Answer:32ビット整数の場合はyes、64ビット整数の場合はno.
(これは、サーバー/デスクトップの汎用CPU環境に適していますが、他のアーキテクチャの動作は異なる場合があります。)
Palical AnswerMalcom McLeanは次のように述べています。
経験的に傾斜している場合は、 this を試してください。
#include <iostream>
#include <limits>
using namespace std;
int main() {
double test;
volatile int test_int;
for(int i=0; i< std::numeric_limits<int>::max(); i++) {
test = i;
test_int = test;
// compare int with int:
if (test_int != i)
std::cout<<"found integer i="<<i<<", test="<<test<<std::endl;
}
return 0;
}
成功時間:0.85メモリ:15240信号:0
Subquestion:わずかな違いの質問について。分数だけ正しい値から外れているが、丸めのために同じ整数に戻るdoubleに変換する整数を持つことは可能ですか?
答えはノーです。なぜなら、同じ値に行き来する整数は、実際には同じ整数値をdoubleで表しているからです。私にとってこれに関する最も簡単な説明(ilkkachuが提案)は、指数2^exponent
を使用すると、ステップ幅は常に2のべき乗でなければならないということです。したがって、最大の52(+1符号)ビット整数を超えると、距離が2未満のdouble値が2つなくなり、丸めの問題が解決されます。
いいえ。64ビット整数型と64ビット浮動小数点型(double
に一般的)があるとします。その整数型には2 ^ 64の値があり、その浮動小数点型には2 ^ 64の値があります。ただし、これらの浮動小数点値の一部(実際にはほとんど)は整数値を表さないため、浮動小数点型は整数型よりも少ない整数値を表すことができます。
答えはノーです。これは、int
sが32ビットの場合にのみ機能します。これは、ほとんどのプラットフォームではtrueですが、標準では保証されていません。
2つの整数は同じdouble表現を共有できます。
たとえば、 this
#include <iostream>
int main() {
int64_t n = 2397083434877565865;
if (static_cast<double>(n) == static_cast<double>(n - 1)) {
std::cout << "n and (n-1) share the same double representation\n";
}
}
印刷します
nと(n-1)は同じ二重表現を共有します
つまり2397083434877565865と2397083434877565864の両方が同じdouble
に変換されます。
ここではint64_t
を使用して64ビット整数を保証していることに注意してください。これは、プラットフォームによってはint
でもある場合があります。
次の2つの質問があります。
すべての整数値は完全にdoubleとして表されていますか?
それはすでに他の人々によって回答されました(TL; DR:int
とdouble
の精度に依存します)。
「同じ」を出力する次のコード例を考えてみてください。[...]これは、アーキテクチャ、コンパイラ、aおよびbの値に当てはまることが保証されていますか?
コードは2つのint
sを追加し、thenは結果をdoubleに変換します。 int
sの合計willは特定の値に対してオーバーフローしますが、2つの個別に変換されたdouble
sの合計は(通常)オーバーフローしません。これらの値では、結果が異なります。
短い答えは「おそらく」です。ポータブルな答えは「どこでもない」です。
それは本当にあなたのプラットフォームに依存し、特に、
double
のサイズと表現int
の範囲IEEE-754倍精度を使用するプラットフォームでは、int
が53ビット以下の場合、mayが真になります。 int
がdouble
より大きいプラットフォームの場合、明らかにfalseです。
std::numeric_limits
およびstd::nextafter
を使用して、ランタイムホストのプロパティを調査できる場合があります。