Pertanyaan saya adalah apakah semua nilai-nilai integer yang dijamin untuk memiliki pilihan ganda representasi.
Pertimbangkan berikut ini contoh kode yang mencetak "Yang":
// 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;
}
}
Ini dijamin untuk menjadi kenyataan untuk setiap arsitektur, setiap compiler, nilai-nilai dari a
dan b
? Akan integer aku
diubah menjadi double
, selalu direpresentasikan sebagai aku.0000000000000
dan tidak, misalnya, seperti saya.000000000001
?
Aku mencoba untuk beberapa nomor lain dan itu selalu benar, tetapi tidak menemukan apa-apa tentang apakah ini kebetulan atau by design.
Catatan: Ini berbeda dari pertanyaan (selain bahasa) karena saya menambahkan dua bilangan bulat.
Disclaimer (seperti yang disarankan oleh Toby Speight): Meskipun IEEE 754 pernyataan yang sangat umum, sebuah implementasi yang diizinkan untuk menggunakan representasi lain yang memenuhi persyaratan bahasa.
Ganda yang direpresentasikan dalam bentuk mantissa * 2^eksponen
, yaitu beberapa bit yang digunakan untuk non-integer bagian dari nomor ganda.
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
Bagian dalam fraksi juga dapat digunakan untuk mewakili sebuah bilangan bulat dengan eksponen yang menghilangkan semua digit setelah titik.
E. g. 2,9979 · 10^4 = 29979.
Sejak umum int
biasanya 32 bit anda dapat mewakili semua `int sebagai double, tapi untuk 64 bit bilangan bulat tentu saja hal ini tidak lagi benar. Untuk lebih tepat (seperti LThode dicatat dalam komentar): IEEE 754 double-precision dapat menjamin ini hingga 53 bit (52 bit significand + implisit terkemuka 1 bit).
Jawaban: ya untuk 32 bit int, tidak untuk 64 bit int.
(Ini adalah benar untuk server/desktop tujuan umum CPU lingkungan, tapi lain arsitektur dapat berperilaku berbeda.)
Jawaban praktis sebagai Malcolm McLean dikatakan: 64 bit ganda yang memadai tipe integer untuk hampir semua bilangan bulat yang mungkin untuk menghitung hal-hal dalam kehidupan nyata.
Untuk secara empiris cenderung, cobalah ini:
#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;
}
waktu Sukses: 0.85 memori: 15240 sinyal:0
Subquestion: Mengenai pertanyaan untuk pecahan perbedaan. Apakah mungkin untuk memiliki sebuah integer yang mengkonversi ke dua yang hanya dari nilai yang benar oleh fraksi, tapi yang mengubah kembali ke yang sama integer karena pembulatan?
Jawabannya adalah tidak, karena setiap bilangan bulat yang mengkonversi bolak-balik ke nilai yang sama, benar-benar merupakan saat yang sama nilai integer di ganda. Bagi saya simplemost penjelasan (disarankan oleh ilkkachu) untuk ini adalah bahwa dengan menggunakan eksponen 2^eksponen
langkah lebar harus selalu kelipatan dari dua. Oleh karena itu, di luar terbesar 52(+1 tanda) bit integer, tidak pernah ada dua nilai-nilai ganda dengan jarak lebih kecil dari 2, yang memecahkan masalah pembulatan.
No. Misalkan anda memiliki 64-bit tipe bilangan bulat dan 64-bit floating-point tipe (yang khas untuk double
). Ada 2^64 nilai yang mungkin bagi yang tipe integer dan ada 2^64 nilai yang mungkin untuk yang floating-point tipe. Tapi beberapa orang floating-point nilai-nilai (dalam kenyataannya, sebagian besar dari mereka) tidak mewakili nilai-nilai integer, sehingga floating-point tipe dapat mewakili kurang integer nilai-nilai dari tipe integer dapat.
Jawabannya adalah tidak ada. Ini hanya bekerja jika `int 32 bit, yang, sementara benar pada kebanyakan platform, isn't dijamin oleh standar.
Dua bilangan bulat dapat berbagi sama double representasi.
Misalnya, ini
#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";
}
}
akan cetak
n dan (n-1) berbagi sama double representasi
I. e. kedua 2397083434877565865 dan 2397083434877565864 akan mengkonversi ke sama ganda
.
Perhatikan bahwa saya menggunakan int64_t
di sini untuk menjamin 64-bit bilangan bulat, yang - tergantung pada platform anda - juga mungkin apa yang int
ini.
Anda memiliki 2 pertanyaan yang berbeda:
semua nilai bilangan bulat sempurna diwakili sebagai ganda?
Itu sudah dijawab oleh orang lain (TL;DR: hal ini tergantung pada ketepatan int
dan double
).
Pertimbangkan berikut ini contoh kode yang mencetak "Yang": [...] ini dijamin benar untuk setiap arsitektur, setiap compiler, nilai-nilai dari a dan b?
Kode anda menambahkan dua int dan *kemudian* mengkonversi hasil ke dua. Jumlah
int akan overflow untuk nilai-nilai tertentu, tetapi jumlah dari dua terpisah-dikonversi `ganda ini tidak akan (biasanya). Bagi mereka nilai-nilai hasil akan berbeda.
Jawaban singkatnya adalah "mungkin". Portabel jawabannya adalah "tidak di mana-mana".
Itu benar-benar tergantung pada platform anda, dan khususnya, pada
ganda
int
Untuk platform yang menggunakan IEEE-754 ganda, mungkin akan benar jika int
adalah 53-bit atau yang lebih kecil. Untuk platform di mana int
lebih besar dari ganda
, it's jelas palsu.
Anda mungkin ingin dapat menyelidiki sifat-sifat pada runtime anda host, menggunakan std::numeric_limits
dan std::nextafter
.