Saya tahu, pertanyaannya sepertinya aneh. Pemrogram terkadang berpikir terlalu banyak. Silakan baca terus ...
Dalam penggunaan CI signed
dan unsigned
bilangan bulat banyak. Saya suka fakta bahwa kompiler memperingatkan saya jika saya melakukan hal-hal seperti menugaskan integer yang ditandatangani ke variabel yang tidak ditandatangani. Saya mendapat peringatan jika saya bandingkan ditandatangani dengan bilangan bulat yang tidak ditandatangani dan banyak lagi.
Saya suka peringatan ini. Mereka membantu saya menjaga kode saya tetap benar.
Mengapa kita tidak memiliki kemewahan yang sama untuk kendaraan hias? Root kuadrat pasti tidak akan pernah mengembalikan angka negatif. Ada juga tempat lain di mana nilai float negatif tidak memiliki arti. Kandidat sempurna untuk pelampung tanpa tanda tangan.
Btw - Saya tidak terlalu tertarik dengan sedikit presisi tambahan yang bisa saya dapatkan dengan menghapus bit tanda dari pelampung. Saya sangat senang dengan float
mereka seperti sekarang. Saya hanya ingin menandai float sebagai unsigned terkadang dan mendapatkan peringatan yang sama dengan yang saya dapatkan dengan bilangan bulat.
Saya tidak mengetahui adanya bahasa pemrograman yang mendukung angka floating-point yang tidak ditandatangani.
Adakah yang tahu mengapa mereka tidak ada?
EDIT:
Saya tahu bahwa FPU x87 tidak memiliki instruksi untuk menangani float yang tidak ditandatangani. Mari kita gunakan instruksi float yang sudah ditandatangani. Penyalahgunaan (mis. Menjadi di bawah nol) dapat dianggap sebagai perilaku yang tidak terdefinisi dengan cara yang sama dengan overflow bilangan bulat yang ditandatangani tidak ditentukan.
Jawaban:
Mengapa C ++ tidak memiliki dukungan untuk float yang tidak ditandatangani adalah karena tidak ada operasi kode mesin yang setara untuk dijalankan oleh CPU. Jadi akan sangat tidak efisien untuk mendukungnya.
Jika C ++ mendukungnya, maka Anda terkadang menggunakan float yang tidak ditandatangani dan tidak menyadari bahwa kinerja Anda baru saja terbunuh. Jika C ++ mendukungnya maka setiap operasi floating point perlu diperiksa untuk melihat apakah ditandatangani atau tidak. Dan untuk program yang melakukan jutaan operasi floating point, ini tidak dapat diterima.
Jadi pertanyaannya adalah mengapa pelaksana perangkat keras tidak mendukungnya. Dan saya pikir jawabannya adalah tidak ada standar float unsigned yang didefinisikan pada awalnya. Karena bahasa ingin kompatibel ke belakang, meskipun bahasa itu ditambahkan tidak dapat memanfaatkannya. Untuk melihat spesifikasi floating point, Anda harus melihat pada standar IEEE 754 Floating-Point .
Anda dapat menghindari tidak memiliki tipe titik mengambang unsigned dengan membuat kelas float unsigned yang merangkum float atau double dan melempar peringatan jika Anda mencoba untuk memasukkan angka negatif. Ini kurang efisien, tetapi mungkin jika Anda tidak menggunakannya secara intensif, Anda tidak akan peduli dengan sedikit kehilangan kinerja.
Saya pasti melihat manfaat memiliki pelampung tanpa tanda tangan. Tetapi C / C ++ cenderung memilih efisiensi yang paling baik untuk semua orang daripada keamanan.
sumber
int
's, semua pengecekan terkait tanda dapat terjadi pada waktu kompilasi. OP menyarankan bahwaunsigned float
akan dilaksanakan secara teraturfloat
dengan pemeriksaan waktu kompilasi untuk memastikan bahwa operasi tidak berarti tertentu tidak pernah dilakukan. Kode dan kinerja mesin yang dihasilkan bisa identik, terlepas dari apakah float Anda ditandatangani atau tidak.Ada perbedaan yang signifikan antara bilangan bulat ditandatangani dan tidak ditandatangani dalam C / C ++:
nilai yang ditandatangani membiarkan bit atas tidak berubah (sign extended), nilai yang tidak ditandatangani menghapus bit atas.
Alasan tidak ada float yang tidak ditandatangani adalah bahwa Anda dengan cepat mengalami semua jenis masalah jika tidak ada nilai negatif. Pertimbangkan ini:
Nilai apa yang dimiliki c? -8. Tapi apa artinya itu dalam sistem tanpa angka negatif. FLOAT_MAX - 8 mungkin? Sebenarnya, itu tidak berfungsi sebagai FLOAT_MAX - 8 adalah FLOAT_MAX karena efek presisi sehingga segala sesuatu menjadi lebih edan. Bagaimana jika itu adalah bagian dari ekspresi yang lebih kompleks:
Ini bukan masalah untuk bilangan bulat karena sifat sistem komplemen 2's.
Juga pertimbangkan fungsi matematika standar: sin, cos dan tan hanya akan bekerja untuk setengah nilai input mereka, Anda tidak dapat menemukan log nilai <1, Anda tidak bisa menyelesaikan persamaan kuadrat: x = (-b +/- root ( bb - 4.ac)) / 2.a, dan sebagainya. Bahkan, itu mungkin tidak akan berfungsi untuk fungsi kompleks karena ini cenderung diimplementasikan sebagai perkiraan polinomial yang akan menggunakan nilai negatif di suatu tempat.
Jadi, pelampung tanpa tanda tidak berguna.
Tapi itu tidak berarti mengatakan bahwa kelas yang rentang memeriksa nilai float tidak berguna, Anda mungkin ingin menjepit nilai ke rentang yang diberikan, misalnya perhitungan RGB.
sumber
2's complement
, tidak akan ada masalah dengan memiliki float yang tidak ditandatangani?value >> shift for signed values leave the top bit unchanged (sign extend)
Apa kamu yakin akan hal itu? Saya pikir itu adalah perilaku yang ditentukan implementasi, setidaknya untuk nilai yang ditandatangani negatif.0.0
, atau mungkin Inf atau NaN. Atau hanya Perilaku yang Tidak Terdefinisi, seperti OP yang disarankan dalam edit pertanyaan. Re: trig functions: jadi jangan mendefinisikan versi input tanpa tandasin
dan sebagainya, dan pastikan untuk memperlakukan nilai pengembaliannya sebagai ditandatangani. Pertanyaannya bukan mengusulkan mengganti float dengan float unsigned, hanya menambahkanunsigned float
sebagai tipe baru.(Sebagai tambahan, Perl 6 memungkinkan Anda menulis
dan kemudian Anda dapat menggunakan
Nonnegative::Float
seperti halnya jenis lainnya.)Tidak ada dukungan perangkat keras untuk operasi floating point yang tidak ditandatangani, jadi C tidak menawarkannya. C sebagian besar dirancang untuk menjadi "rakitan portabel", yaitu, sedekat mungkin dengan logam tanpa terikat ke platform tertentu.
[sunting]
C seperti perakitan: apa yang Anda lihat adalah persis apa yang Anda dapatkan. Sebuah implisit "Saya akan memeriksa bahwa pelampung ini tidak negatif untuk Anda" bertentangan dengan filosofi desainnya. Jika Anda benar-benar menginginkannya, Anda dapat menambahkan
assert(x >= 0)
atau serupa, tetapi Anda harus melakukannya secara eksplisit.sumber
of ...
tidak diuraikan.Saya percaya int unsigned dibuat karena kebutuhan untuk margin nilai yang lebih besar daripada yang ditandatangani int dapat menawarkan.
Float memiliki margin yang jauh lebih besar, sehingga tidak pernah ada kebutuhan 'fisik' untuk float yang tidak ditandatangani. Dan ketika Anda menunjukkan diri Anda dalam pertanyaan Anda, tambahan 1 bit presisi bukanlah apa-apa untuk membunuh.
Sunting: Setelah membaca jawaban oleh Brian R. Bondy , saya harus mengubah jawaban saya: Dia pasti benar bahwa CPU yang mendasarinya tidak memiliki operasi float yang tidak ditandatangani. Namun, saya mempertahankan keyakinan saya bahwa ini adalah keputusan desain berdasarkan alasan yang saya nyatakan di atas ;-)
sumber
Saya pikir Treb ada di jalur yang benar. Ini lebih penting untuk bilangan bulat bahwa Anda memiliki tipe korespondensi yang tidak ditandatangani. Itu adalah yang digunakan dalam bit-shifting dan digunakan dalam bit-maps . Sedikit tanda masuk ke jalan. Misalnya, menggeser-kanan nilai negatif, nilai yang dihasilkan adalah implementasi yang didefinisikan dalam C ++. Melakukan hal itu dengan integer yang tidak ditandatangani atau meluap seperti itu memiliki semantik yang terdefinisi dengan sempurna karena tidak ada yang menghalangi.
Jadi untuk bilangan bulat setidaknya, kebutuhan untuk tipe unsigned yang terpisah lebih kuat dari sekedar memberikan peringatan. Semua poin di atas tidak perlu dipertimbangkan untuk mengapung. Jadi, menurut saya, tidak ada kebutuhan nyata untuk dukungan perangkat keras untuk mereka, dan C sudah tidak mendukung mereka pada saat itu.
sumber
C99 mendukung bilangan kompleks, dan tipe umum dari sqrt, jadi
sqrt( 1.0 * I)
akan negatif.Para komentator menyoroti sedikit gloss di atas, karena saya merujuk pada
sqrt
makro tipe-generik daripada fungsi, dan itu akan mengembalikan nilai floating point skalar dengan memotong kompleks ke komponen sebenarnya:Ini juga berisi kentut-otak, karena bagian nyata dari sqrt dari setiap bilangan kompleks adalah positif atau nol, dan sqrt (1.0 * I) adalah sqrt (0.5) + sqrt (0.5) * I not -1.0.
sumber
sqrt(-0.0)
sering menghasilkan-0.0
. Tentu saja -0,0 bukan nilai negatif .Saya kira itu tergantung pada spesifikasi floating-point IEEE saja yang ditandatangani dan sebagian besar bahasa pemrograman menggunakannya.
Artikel Wikipedia tentang angka-angka floating-point IEEE-754
Sunting: Juga, seperti dicatat oleh orang lain, sebagian besar perangkat keras tidak mendukung pelampung non-negatif, sehingga jenis pelampung yang normal lebih efisien untuk dilakukan karena ada dukungan perangkat keras.
sumber
Saya pikir alasan utama adalah bahwa pelampung tanpa tanda akan memiliki kegunaan yang benar-benar terbatas dibandingkan dengan int unsigned. Saya tidak membeli argumen bahwa itu karena perangkat keras tidak mendukungnya. Prosesor yang lebih tua tidak memiliki kemampuan floating point sama sekali, itu semua ditiru dalam perangkat lunak. Jika float yang tidak ditandatangani bermanfaat, mereka akan diimplementasikan dalam perangkat lunak terlebih dahulu dan perangkat keras akan mengikutinya.
sumber
Tipe integer yang tidak ditandai dalam C didefinisikan sedemikian rupa untuk mematuhi aturan cincin aljabar abstrak. Misalnya, untuk nilai X dan Y apa pun, menambahkan XY ke Y akan menghasilkan X. Jenis integer yang tidak ditandatangani dijamin untuk mematuhi aturan-aturan ini dalam semua kasus yang tidak melibatkan konversi ke atau dari jenis numerik lainnya [atau jenis tanpa tanda ukuran berbeda] , dan jaminan itu adalah salah satu fitur terpenting dari jenis-jenis tersebut. Dalam beberapa kasus, ada baiknya melepaskan kemampuan untuk mewakili angka negatif dengan imbalan jaminan tambahan yang hanya bisa diberikan oleh tipe yang tidak bertanda tangan. Tipe floating-point, apakah ditandatangani atau tidak, tidak dapat mematuhi semua aturan cincin aljabar [misalnya mereka tidak dapat menjamin bahwa X + YY akan sama dengan X], dan memang IEEE tidak bahkan tidak memungkinkan mereka untuk mematuhi aturan kelas kesetaraan [dengan mengharuskan nilai-nilai tertentu dibandingkan tidak setara dengan diri mereka sendiri]. Saya tidak berpikir tipe floating-point "unsigned" dapat mematuhi aksioma yang tidak bisa dilakukan oleh tipe floating-point, jadi saya tidak yakin apa kelebihan yang ditawarkannya.
sumber
IHMO itu karena mendukung tipe floating-point yang ditandatangani dan tidak ditandatangani baik dalam perangkat keras maupun perangkat lunak akan terlalu merepotkan
Untuk tipe integer kita dapat memanfaatkan yang sama logika unit untuk kedua operasi integer ditandatangani dan unsigned dalam kebanyakan situasi menggunakan properti yang bagus komplemen 2, karena hasilnya identik dalam kasus-kasus untuk add, sub, non-pelebaran mul dan kebanyakan operasi bitwise. Untuk operasi yang membedakan antara versi yang ditandatangani dan yang tidak ditandatangani, kami masih dapat berbagi sebagian besar logika . Sebagai contoh
INT_MIN
. Secara teoritis juga mungkin, mungkin tidak digunakan pada perangkat keras, namun ini berguna pada sistem yang hanya mendukung satu jenis perbandingan (seperti 8080 atau 8051)Sistem yang menggunakan komplemen 1 juga hanya perlu sedikit modifikasi pada logika karena itu hanya membawa sedikit melilit ke bit yang paling signifikan. Tidak yakin tentang sistem sign-magnitude tetapi sepertinya mereka menggunakan komplemen 1 secara internal sehingga hal yang sama berlaku
Sayangnya kami tidak begitu mewah untuk tipe floating-point. Dengan hanya membebaskan bit tanda kita akan memiliki versi yang tidak ditandatangani. Tapi untuk apa kita menggunakan bit itu?
Tetapi kedua pilihan membutuhkan penambah yang lebih besar untuk mengakomodasi rentang nilai yang lebih luas. Itu meningkatkan kompleksitas logika sementara bit atas penambah duduk di sana sebagian besar tidak digunakan. Lebih banyak sirkuit akan diperlukan untuk perkalian, divisi atau operasi kompleks lainnya
Pada sistem yang menggunakan perangkat lunak titik-mengambang, Anda memerlukan 2 versi untuk setiap fungsi yang tidak diharapkan selama memori sangat mahal, atau Anda harus menemukan beberapa cara "rumit" untuk berbagi bagian dari fungsi yang ditandatangani dan tidak ditandatangani.
Namun perangkat keras floating-point sudah ada jauh sebelum C ditemukan , jadi saya percaya pilihan dalam C adalah karena kurangnya dukungan perangkat keras karena alasan yang saya sebutkan di atas
Yang mengatakan, ada beberapa format floating-point unsigned khusus , terutama untuk keperluan pemrosesan gambar, seperti tipe floating-point 10 dan 11-bit Khronos group
sumber
Saya menduga itu karena prosesor dasar yang ditargetkan oleh kompiler C tidak memiliki cara yang baik untuk menangani angka floating point yang tidak ditandatangani.
sumber
Pertanyaan bagus.
Jika, seperti yang Anda katakan, itu hanya untuk peringatan waktu kompilasi dan tidak ada perubahan dalam perilaku mereka sebaliknya maka perangkat keras yang mendasarinya tidak terpengaruh dan karena itu hanya akan menjadi perubahan C ++ / Compiler.
Saya telah memenangkan yang sama sebelumnya, tetapi masalahnya adalah: Itu tidak akan banyak membantu. Paling-paling kompiler dapat menemukan tugas statis.
Atau lebih lama secara minimalis
Tapi itu saja. Dengan tipe integer yang tidak ditandatangani, Anda juga mendapatkan sampul yang ditentukan, yaitu berperilaku seperti aritmatika modular.
setelah ini 'uc' memiliki nilai 255.
Sekarang, apa yang akan dilakukan oleh kompiler dengan skenario yang sama dengan tipe float-unsigned? Jika nilainya tidak diketahui pada waktu kompilasi, ia perlu menghasilkan kode yang pertama-tama mengeksekusi perhitungan dan kemudian melakukan tanda-cek. Tetapi bagaimana ketika hasil dari perhitungan seperti itu akan mengatakan "-5.5" - nilai mana yang harus disimpan dalam float yang dinyatakan tidak ditandatangani? Orang dapat mencoba aritmatika modular seperti untuk tipe integral, tetapi itu datang dengan masalah sendiri: Nilai terbesar adalah tak terhingga tak terhingga .... itu tidak bekerja, Anda tidak dapat memiliki "tak terhingga - 1". Pergi untuk nilai berbeda terbesar yang bisa dipegang juga tidak akan benar-benar berfungsi karena di sana Anda mengalami precisi. "NaN" akan menjadi kandidat.
Terakhir ini tidak akan menjadi masalah dengan nomor titik tetap karena ada modulo yang didefinisikan dengan baik.
sumber