- Pengurangan floating-point IEEE-754 dapat digunakan untuk membuat rangkaian biner arbitrer dengan memanfaatkan aturan nol bertanda dan tanda hasil
- Jika
-0dianggap false dan+0dianggap true, makax - ydalam mode pembulatan default bekerja sepertiA ∨ ¬B, yaitu gerbang IMPLY dengan argumen yang dibalik - Gerbang ini dapat membuat NOT jika tersedia konstanta false, dan kombinasi NOT + IMPLY menjadi himpunan gerbang logika yang lengkap secara fungsional
- Contoh Python membedakan secara langsung tanda
-0.0dan0.0untuk mengimplementasikanf_not,f_or,f_and,f_xorsemuanya berbasis pengurangan - Contoh Rust merepresentasikan bilangan bulat 8-bit dengan array
f32, menghitung 23 + 19 = 42, dan membutuhkan sekitar 120 instruksi floating-point untuk penjumlahan dua bilangan bulat 8-bit
Titik awal yang dibentuk oleh aturan tanda IEEE-754
- Pengurangan floating-point IEEE-754 memiliki kelengkapan fungsional
- Lengkap secara fungsional berarti operasi tersebut saja sudah cukup untuk membangun rangkaian biner arbitrer
- Intinya ada pada aturan bit tanda di bagian 6.3 standar IEEE 754-2019
- Pengurangan
x - ydiperlakukan sebagai penjumlahanx + (-y) - Nol dapat memiliki tanda, sehingga
-0dan+0diperlakukan sebagai nilai yang berbeda - Namun dalam perbandingan IEEE-754,
-0 == +0bernilai true - Selama input dan hasil bukan NaN, tanda dari jumlah atau selisih mengikuti aturan tanda operan
- Jika selisih dua nilai dengan tanda yang sama tepat 0, hasilnya menjadi
+0pada mode pembulatan selainroundTowardNegative
- Pengurangan
- Konstruksi berikutnya mengasumsikan mode pembulatan default
roundTiesToEven- Ini juga bekerja dengan cara serupa pada
roundTowardNegative
- Ini juga bekerja dengan cara serupa pada
Tabel kebenaran saat mengurangkan sesama 0
- Jika hanya
-0dan+0yang dikurangkan, hasilnya sebagai berikut-0 - -0 = +0-0 - +0 = -0+0 - -0 = +0+0 - +0 = +0
- Jika
-0dipetakan ke false dan+0ke true, tabel kebenaran keluarannya menjadi seperti ini0 0 -> 10 1 -> 01 0 -> 11 1 -> 1
- Tabel kebenaran ini sama dengan
A ∨ ¬B, atau gerbang IMPLY dalam bentukB → A- Dibandingkan gerbang IMPLY yang umum, ini adalah bentuk dengan argumen terbalik
Menjadi lengkap secara fungsional jika ada konstanta false
- Tabel kebenaran ini menjadi lengkap secara fungsional jika ada akses ke konstanta false
- Dengan konstanta false, kita bisa membuat gerbang NOT
- NOT + IMPLY adalah himpunan yang lengkap secara fungsional
- NAND dan NOR lengkap secara fungsional sendirian tanpa memerlukan konstanta tertentu
- Saat membuat mikrochip, ini memberi keuntungan karena hanya perlu memproduksi satu jenis komponen
- Tidak perlu merutekan sinyal low yang konsisten untuk membuat gerbang NOT
Rangkaian logika berbasis pengurangan dalam Python
- Contoh Python mendefinisikan
-0.0sebagai false dan0.0sebagai true- Dalam IEEE-754,
+0dan-0sama dalam perbandingan, jadi keduanya dibedakan dengan mengekstrak tanda memakaimath.copysign
- Dalam IEEE-754,
- Gerbang NOT memanfaatkan sifat
-0 - xyang membalik tanda nolf_not = lambda x: f_false - xf_not(-0.0)menjadi truef_not(+0.0)menjadi false
- Gerbang OR dibangun dengan membalik tanda argumen kedua lalu melakukan pengurangan
f_or = lambda a, b: a - f_not(b)- Hanya bernilai false saat kedua argumen sama-sama
-0, dan true pada kasus lainnya
- AND dan XOR juga bisa dibangun dari kombinasi OR dan NOT
f_and = lambda a, b: f_not(f_or(f_not(a), f_not(b)))f_xor = lambda a, b: f_or(f_and(f_not(a), b), f_and(a, f_not(b)))
Bilangan bulat perangkat lunak yang dibuat dengan Rust
- Contoh Rust menggunakan
Bit = f32, laluZERO = -0.0danONE = 0.0untuk merepresentasikan bit not,or,and,xorsemuanya diimplementasikan berbasis pengurangan floating-point, lalu dipakai untuk membuat full adderadderSoftU8 = [Bit; 8]digunakan untuk merepresentasikan bilangan bulat 8-bitto_softu8mengubah tiap bit dariu8menjadiONEatauZEROfrom_softu8memeriksa tanda tiap elemen lalu mengubahnya kembali menjadiu8
- Program contoh mengubah 23 dan 19 menjadi
SoftU8, menjumlahkannya, lalu mencetak 42 - Menjumlahkan dua bilangan bulat 8-bit membutuhkan sekitar 120 instruksi floating-point
- Pada x86-64 tidak ada instruksi pembalikan tanda floating-point yang nyata, sehingga kompiler menggunakan mask dan XOR untuk men-toggle bit tanda, yaitu bit paling signifikan dari bilangan floating-point IEEE-754
2 komentar
Pendapat di Hacker News
Penyalahgunaan instruksi floating-point yang aneh seperti ini terbayang bisa dipakai oleh suatu DRM sebagai cara untuk mengobfuskasi mesin virtual.
Langkah berikutnya mungkin membuat compiler yang memanfaatkan sifat ini untuk menjalankan kode sumber biasa sebagai integer floating-point, lalu menambahkan semacam FFI untuk memanggil API OS biasa.
Ini adalah bukti konstruktif bahwa mekanisme penanganan exception pada Intel MMU bersifat Turing-complete.
Mereka membuat assembler yang mengubah instruksi
Move, Branch if Zero, Decrementmenjadi source C yang menyiapkan berbagai tabel kontrol prosesor, dan setelah kode itu dijalankan, CPU melakukan komputasi dengan cara mencoba memicu exception tanpa mengeksekusi satu instruksi pun.Secara opsional, assembler juga bisa menghasilkan instruksi X86 yang menampilkan variabel pada framebuffer VGA dan memindahkan kontrol di antara instruksi tampilan native dan instruksi trap weird machine.
Saya teringat video luar biasa ini yang membuat komputasi hanya dengan NaN dan infinity IEEE-754: https://www.youtube.com/watch?v=5TFDG-y-EHs
Kontennya sangat nerdy, penuh pemikiran, lucu, dan cara penyampaiannya juga sangat bagus.
Sangat direkomendasikan, terutama untuk pembaca HN.
Dalam cerita pendek Coding Machines, penyalahgunaan bit tanda dengan cara serupa menjadi petunjuk besar bahwa AI sungguhan telah lepas ke dunia.
https://www.teamten.com/lawrence/writings/coding-machines/
Sebagai materi terkait, ada https://dougallj.wordpress.com/2020/05/10/bitwise-conversion...
Ini adalah implementasi yang mengonversi satu double IEEE-754 menjadi sepasang dua double yang berisi nilai integer 32 bit bawah dan 32 bit atas dari representasi bit argumennya, hanya dengan memakai penjumlahan/pengurangan/perkalian double.
Melihat tabel kebenarannya, pengurangan jelas truth-preserving, jadi tampaknya secara nyata tidak mungkin functionally complete.
Apa yang saya lewatkan?
Tanpa konstanta ini ia tidak functionally complete, dan berbeda dari NAND yang bisa membuat false dari nilai apa pun.
Inti tulisan itu adalah menunjukkan bahwa hanya dengan signed zero dan pengurangan floating-point kita bisa meniru rangkaian arbitrer, dan saya menganggap functional completeness sebagai istilah paling ringkas untuk menyatakannya, tetapi jika hanya melihat tabel kebenaran secara ketat, memang aturannya agak dipelintir, jadi akan saya perjelas di tulisan.
Dengan pengurangan dan 0, kita membuat false sebagai -0.0, lalu memperoleh himpunan functionally complete
{->, _|_}yang ada di Wikipedia [1].[1] https://en.wikipedia.org/wiki/Functional_completeness
Saya tidak setuju dengan klaim bahwa bit pengurangan itu sendiri functionally complete.
Karena truth-preserving, tampaknya benar bahwa ia tidak functionally complete.
Isinya adalah bahwa “setiap himpunan konektif dua elemen yang mencakup NOT dan salah satu dari {AND, OR, IMPLY} adalah subset minimal functionally complete dari {NOT, AND, OR, IMPLY, IFF}”.
[1] https://en.wikipedia.org/wiki/Functional_completeness
Lagi pula, bagaimana bisa tahu sejak awal bahwa tabel kebenaran itu truth-preserving? Tabel kebenaran bukan argumen logis.
Jika kelengkapan fungsional berarti bisa membuat rangkaian logika apa pun, apakah pengurangan floating-point IEEE-754 secara praktis berarti Turing-complete? Atau tidak?
Kelengkapan fungsional tidak mencakup kemampuan iterasi yang diperlukan untuk menjadi Turing-complete
Turing-completeness sering disalahgunakan ketika yang dimaksud sebenarnya kelengkapan fungsional, dan ada juga kasus orang mencampuradukkan keduanya atau memakai istilah itu karena terdengar lebih menarik sebagai judul blog/artikel
movsebenarnya tidak Turing-complete dan membutuhkan instruksijmp: https://harrisonwl.github.io/assets/courses/malware/spring20...Sistem enkripsi homomorfik lengkap secara fungsional, tetapi tidak Turing-complete. Sebab iterasi akan membocorkan jumlah operasi yang dilakukan dan memecahkan enkripsinya
Dengan gerbang NAND, kita bisa membuat mesin yang Turing-complete, tetapi mengatakan bahwa gerbang NAND itu Turing-complete sama seperti mengatakan kita bisa tinggal di dalam batu bata
Kita tidak bisa tinggal di dalam batu bata, tetapi kita bisa membangun rumah dari batu bata dan tinggal di dalamnya
“Kurangi dan bercabang jika kurang dari atau sama dengan 0” adalah satu instruksi yang Turing-complete
https://en.wikipedia.org/wiki/One-instruction_set_computer
Dulu saya pernah memposting ini di thread /r/programming, tetapi saya taruh juga di sini
Adder bisa diimplementasikan hanya dengan 11 kali pengurangan
fn adder(a: Bit, b: Bit, c: Bit) -> (Bit, Bit) {let r0 = c - b;let r1 = c - r0;let r2 = ZERO - r0;let r3 = b - r1;let r4 = r2 - r3;let r5 = a - r4;let r6 = r4 - a;let r7 = ZERO - r5;let r8 = r7 - r1;let r9 = r7 - r6;let r10 = ZERO - r8;(r9, r10)}Kalau yang dimaksud adalah “integer yang diimplementasikan dalam software hanya menggunakan operasi floating-point”, pada dasarnya itu sama seperti semua upaya di JavaScript untuk memakai number seolah-olah int
Kalimat “Jika tanda kedua significand sama, output juga harus memiliki tanda itu. Namun pada x−y, jika tanda x dan y berbeda, output harus memiliki tanda x” sedikit keliru, atau mencampuradukkan kata tanda dalam dua makna
Jika keduanya bertanda positif seperti x=5, y=10, maka x-y menjadi -5 dan bertanda negatif
Bahkan jika diasumsikan tanda variabel y benar-benar dibalik, jika memilih -3 dan -6, yang terakhir dibalik menjadi 6 dan hasilnya +3, sehingga tandanya berbeda dari x
Begitu pula -3 dan -6; karena tanda x dan y sama, kondisi untuk pengurangan itu tidak terpenuhi
Contohnya membahas tanda yang sama
Ada kesalahan pada judulnya. Bukan berarti pengurangan sudah selesai, melainkan bahwa semua fungsi dapat diekspresikan dengan pengurangan, sehingga disebut lengkap secara fungsional.