Tantangan Posisi Dewasa

Sudah ada beberapa artikel tentang Habré ( satu , dua , dua dan setengah ) yang ditujukan untuk format floating point Posit baru, penulis yang menyajikannya sebagai yang lebih unggul dari standar IEEE 754 float dalam segala hal. Format baru ini juga menemukan kritik ( satu , dua ) yang mengklaim bahwa kelemahan Posit lebih besar daripada kelebihannya. Tetapi bagaimana jika kita benar-benar memiliki format revolusioner baru, dan kritik itu hanya disebabkan oleh kecemburuan dan ketidakmampuan orang-orang yang mengkritik? Nah, cara terbaik untuk mengetahuinya adalah dengan mengambil dan menghitung sendiri.

Pendahuluan


Kelebihan dari format baru ditunjukkan oleh contoh-contoh sederhana dengan penambahan / penggandaan angka dari urutan yang sama, yang menghasilkan akurasi satu atau dua digit lebih tinggi. Namun, dalam perhitungan nyata, plus / minus satu bit kesalahan operasi tunggal tidak masalah, karena kami menghitungnya dengan akurasi terbatas. Akumulasi kesalahan sebagai hasil dari urutan operasi adalah penting, ketika setelah beberapa waktu kesalahan dalam digit yang lebih rendah mulai mengarah pada kesalahan yang lebih lama. Inilah yang akan kami coba alami.

Persiapan


Untuk pengujian, saya mengambil implementasi Posit dengan judul pathos dari sini . Untuk mengkompilasinya di Visual Studio, kami harus menambahkan baris #define CLZ (n) __lzcnt (n) dalam file util.h dan mengganti 0.f / 0.f dalam file posit.cpp dengan std :: numeric_limits <float> :: quiet_NaN (). By the way, implementasi untuk fungsi matematika dasar (baik, kecuali untuk root) juga tidak ditemukan di perpustakaan ini - ini adalah alasan lain untuk mencurigai ada sesuatu yang salah.

Uji 1. Penggandaan bilangan kompleks


Transformasi Fourier, dihitung menggunakan aritmatika kompleks, digunakan sedapat mungkin. Pada awalnya, saya ingin menguji Posit pada transformasi Fourier; tetapi karena akurasinya sangat tergantung pada implementasi, untuk pengujian yang benar Anda harus mempertimbangkan semua algoritma dasar, yang agak memakan waktu; oleh karena itu, Anda dapat memulai dengan operasi yang lebih sederhana - penggandaan bilangan kompleks.

Jika kita mengambil vektor tertentu dan memutarnya 360 kali 1 °, maka pada akhirnya kita akan mendapatkan vektor asli yang sama. Bahkan, hasilnya akan sedikit berbeda karena akumulasi kesalahan - dan semakin besar jumlah belokan, semakin besar kesalahannya. Jadi, gunakan kode sederhana ini

complex<T> rot(cos(a), sin(a)); complex<T> vec(length, 0); for (long i = 0; i < count; i++) { vec *= rot; } cout << "error: " << stdev(vec.real() - length, vec.imag()) << endl; 

kami memutar vektor dengan berbagai jenis data, dan kami akan menganggap kesalahan sebagai penyimpangan kuadrat dari vektor yang dihasilkan dari aslinya (yang juga dapat diartikan sebagai panjang vektor perbedaan).

Pertama, ambil vektor satuan sebagai yang paling mendukung Posit:
iterasi4100100010.000100.000
dobel00000
mengapung00,000000360,000010380,00018580,0001961
menempatkan00,000000730,000005340,00004110,0004468

Belum ada pemimpin yang jelas di sini - keuntungannya dua kali lipat dari yang satu atau yang lain. Tambah panjang vektor yang diputar ke 1000:
iterasi4100100010.000100.000
dobel00000
mengapung00,000280,01030,180,19
menempatkan00,002130,01880,162.45

Nilai kesalahan hampir sama. Silakan - 1.000.000:
iterasi4100100010.000100.000
dobel000,000000020,000000420,0000036
mengapung00,3312.0185.8198.1
menempatkan08.1271.0769.210706.8

Di sini Posit sudah percaya diri tertinggal, dan kesalahan ganda mulai merayap ke float. Mari kita mengambil waktu yang lebih lama lagi - 10 10 untuk sepenuhnya menghargai keunggulan format floating-point:
iterasi4100100010.000100.000
dobel0,000002450,000015360,00020410,00409510,03621497
mengapung0,000002456003.888111.81 836 254.01965083.0
menempatkan9216.01287208.714443543,7202630144.41784050328.2

Di sini hal yang paling menarik di awal, di 4 iterasi - ketika float memberikan kesalahan sepadan dengan double, dan Posit sudah memiliki hasil yang sepenuhnya salah.

Tes 2. Perhitungan polinomial rasional


Karena tidak ada fungsi matematika di perpustakaan asli, kami akan mencoba melakukan sesuatu sendiri. Banyak fungsi yang kurang didekati dengan ekspansi dalam deret Taylor, dan lebih mudah untuk dihitung melalui aproksimasi oleh polinomial rasional. Perkiraan ini dapat diperoleh dengan berbagai cara, termasuk murni analitis - melalui pendekatan Padé . Kami akan mengambilnya untuk pengujian, apalagi, dengan koefisien yang cukup besar sehingga mereka juga menjalani pembulatan sebelum perhitungan.

Menggunakan Wolfram Mathematica dan perintah PadeApproximant [Sin [x], {x, 0, {11, 11}}]
kami mendapatkan polinomial rasional untuk mendekati sinus, yang menyediakan akurasi ganda dalam kisaran dari sekitar -2 hingga 2:

 frac frac481959816488503x363275871831577908403200+ frac23704595077729x942339845201815607040 frac2933434889971x73360305474747617703157122660 frac109061004303x3722459832892+x frac37291724011x1011008359752472057830400+ frac3924840709x848848484848484848x6168015258737363520+ frac1679739379x413726736824948+ frac34046903537x22167379498676+1


Skema Horner biasanya digunakan langsung untuk perhitungan untuk menghemat perhitungan. Dalam kasus kami (menggunakan HornerForm) akan terlihat seperti

 template< typename T > T padesin(T x) { T xx = x*x; return (x*(T(363275871831577908403200.) + xx*(-T(54839355237791393068800.) + xx*(T(2120649063015013090560.) + xx*(-T(31712777908498486800.) + xx*(T(203385425766914820.) - T(481959816488503.) * xx)))))) / (T(363275871831577908403200.) + xx*(T(5706623400804924998400.) + xx*(T(44454031219351353600.) + xx* (T(219578286347980560.) + xx*(T(707177798947620.) + T(1230626892363.) * xx))))); } 


Mari kita lihat:
x = 0,5x = 1x = 2
dosa (x)0.4794255386042030.84147098480789650,9092974268256817
dobel0.4794255386042030.84147098480789650,909297426825681 6
mengapung0.4794255 4950714110.84147095680 236820,9092974 066734314
menempatkan0.47 889610379934310.84 244372695684430,9 110429435968399

x = 3x = 4x = 5
dosa (x)0,1411200080598672-0.7568024953079282-0.9589242746631385
dobel0.14112000805 85958-0.75680249 60833886-0,958924 3758030122
mengapung0,1411200 165748596-0.7568024 396896362-0.9589243 531227112
menempatkan0,14 44759201258421-0,7 614213190972805-0,9 691629931330681

Seperti yang Anda lihat, situasi dengan Posit di sini terlihat menyedihkan - hampir tidak ada dua angka penting yang diputar.

Kesimpulan


Sayangnya, keajaiban tidak terjadi dan revolusi dibatalkan. Keuntungan Posit yang ditunjukkan pada perhitungan tunggal tidak lebih dari sebuah trik, harga yang merupakan penurunan akurat dalam akurasi dalam perhitungan nyata "berat". Satu-satunya alasan masuk akal untuk menggunakan Posit daripada IEEE 754 float atau titik tetap adalah alasan agama. Dengan menggunakan format ajaib, keakuratan yang dipastikan oleh iman suci penciptanya, dapat membawa banyak keajaiban ke program Anda!

Kode sumber PS untuk verifikasi dan kritik .

PPS Lanjutan .

Source: https://habr.com/ru/post/id467735/


All Articles