Kayan nokta matemati─či bozuk mu?


Al─▒nan cevaba git


A┼ča─č─▒daki kodu g├Âz ├Ân├╝nde bulundurun:

 0.1 + 0.2 == 0.3  ->  false
 
 0.1 + 0.2         ->  0.30000000000000004
 

Bu yanl─▒┼čl─▒klar neden oluyor?


2757









Cevap say─▒s─▒n─▒ say: 30






─░kili kayan nokta matematik b├Âyle. ├ço─ču programlama dilinde, IEEE 754 standard─▒na dayan─▒r . JavaScript, Java ile ayn─▒ olan 64 bit kayan nokta g├Âsterimini kullan─▒r double . Sorunun temel noktas─▒, say─▒lar─▒n bu say─▒ bi├žiminde bir tam say─▒ ├žarp─▒ iki g├╝c├╝yle temsil edilmesidir; Rasyonel say─▒lar (├Ârne─čin 0.1 , hangi 1/10 olan payda iki g├╝├ž tam olarak temsil edilemez de─čildir).

─░├žin 0.1 standart i├žinde binary64 format─▒nda, temsili tam olarak yaz─▒labilir

  • 0.1000000000000000055511151231257827021181583404541015625 ondal─▒kta veya
  • 0x1.999999999999ap-4 i├žinde C99 hexfloat g├Âsterimde .

Buna kar┼č─▒l─▒k, rasyonel say─▒ 0.1 oldu─ču, 1/10 tam olarak yaz─▒labilir

  • 0.1 ondal─▒kta veya
  • 0x1.99999999999999...p-4 C99 hexfloat notasyonunun bir analogunda, burada 9'lar─▒n ... bitmeyen bir sekans─▒n─▒ temsil eder.

Sabitler 0.2 ve 0.3 program─▒n─▒zdaki ger├žek de─čerlerine de yakla┼č─▒lacakt─▒r. O en yak─▒n olur double ├╝zere 0.2 rasyonel say─▒s─▒ndan daha fazla 0.2 ama en yak─▒n oldu─ču double i├žin 0.3 rasyonel say─▒s─▒ndan daha k├╝├ž├╝kt├╝r 0.3 . Toplam─▒ 0.1 ve 0.2 r├╝zg├órlar─▒ rasyonel say─▒lardan daha b├╝y├╝kt├╝r 0.3 ve bu nedenle kodunuzdaki sabitle ayn─▒ fikirde de─čildir.

Kayan nokta aritmetik sorunlar─▒n─▒n olduk├ža kapsaml─▒ bir tedavisi, Her Bilgisayar Bilim ─░nsan─▒n─▒n Kayan Nokta Aritmeti─či Hakk─▒nda Bilmeniz Gerekenleridir . Sindirimi daha kolay bir a├ž─▒klama i├žin, bkz. Floating-point-gui.de .

Yan Not: T├╝m konumsal (N baz) say─▒ sistemleri bu sorunu hassasiyetle payla┼č─▒r

D├╝z eski ondal─▒k basamak (10 say─▒) ayn─▒ sorunlara sahiptir, bu y├╝zden 1/3 gibi rakamlar 0.333333333 ...

Ondal─▒k sistemle temsil edilmesi kolay olan ancak ikili sisteme uymayan bir say─▒ya (3/10) rastlad─▒n─▒z. Her iki y├Ânde de (bir dereceye kadar) gider: 1/16, ondal─▒k say─▒daki (0.0625) ├žirkin bir say─▒d─▒r, ancak ikili dosyada, 10.000'in ondal─▒k basama─č─▒ndaki kadar d├╝zg├╝n g├Âr├╝n├╝yor (0.0001) ** - e─čer G├╝nl├╝k ya┼čamlar─▒m─▒zda 2 numaral─▒ bir say─▒ sistemini kullanma al─▒┼čkanl─▒─č─▒, o say─▒ya bile bakars─▒n─▒z ve bir ┼čeyi yar─▒ya indirmek, tekrar yar─▒ya indirmek ve tekrar tekrar oraya varabilece─činizi i├žg├╝d├╝sel olarak anlars─▒n─▒z.

** Elbette, kayan nokta say─▒lar─▒ haf─▒zada tam olarak bu ┼čekilde saklanmaz (bir bilimsel g├Âsterim ┼čekli kullan─▒rlar). Bununla birlikte, ikili kayan nokta kesinlikli hassasiyet hatalar─▒n─▒n ├žo─čalmaya meyilli oldu─ču noktas─▒n─▒ g├Âstermektedir, ├ž├╝nk├╝ birlikte ├žal─▒┼čmakla genellikle ilgilendi─čimiz "ger├žek d├╝nya" say─▒lar─▒, ├žo─ču zaman onluk g├╝├žlerdir - ancak yaln─▒zca ondal─▒k say─▒ sistemi kulland─▒─č─▒m─▒z i├žin bug├╝n. Bu nedenle, "her 7 / 5'ten 5" yerine% 71 gibi ┼čeyler s├Âyleyece─čiz (% 71 bir yakla┼č─▒md─▒r, ├ž├╝nk├╝ 5/7 tam olarak herhangi bir ondal─▒k say─▒ ile g├Âsterilemez).

Yani hay─▒r: ikili kayan nokta say─▒lar─▒ k─▒r─▒lmaz, sadece di─čer her N temel say─▒ sistemi gibi kusurlu olurlar :)

Yan Taraf Not: Programlamada Y├╝zd├╝rme ile ├çal─▒┼čma

Uygulamada, bu hassasl─▒k sorunu, kayan nokta say─▒lar─▒n─▒z─▒, g├Âr├╝nt├╝lemeden ├Ânce ilgilendi─činiz bir├žok ondal─▒k basama─ča yuvarlamak i├žin yuvarlama i┼člevlerini kullanman─▒z gerekti─či anlam─▒na gelir.

Ayr─▒ca e┼čitlik testlerini baz─▒ toleranslara izin veren kar┼č─▒la┼čt─▒rmalarla de─či┼čtirmeniz gerekir, yani:

Do not do if (float1 == float2) { ... }

Bunun yerine yap─▒n if (Math.Abs(float1 - float2) < myToleranceValue) { ... } .

├ľzel uygulaman─▒z i├žin myToleranceValue'un se├žilmesi gerekiyor - ve ne kadar "k─▒p─▒rdatma odas─▒" haz─▒rlamaya ne kadar haz─▒r olaca─č─▒n─▒z ve kar┼č─▒la┼čt─▒raca─č─▒n─▒z en b├╝y├╝k rakam─▒n ne olaca─č─▒ (hassasiyet kayb─▒ nedeniyle) olacak sorunlar). Se├žti─činiz dilde "double.Epsilon" stil sabitlerine dikkat edin (Javascript'te Number.EPSILON). Bunlar olup tolerans de─čerleri olarak kullan─▒l─▒r.


2085







Bir Donan─▒m Tasar─▒mc─▒s─▒n─▒n Perspektifi

Kayan nokta donan─▒m─▒ tasarlay─▒p olu┼čturdu─čum i├žin buna bir donan─▒m tasar─▒mc─▒s─▒ bak─▒┼č a├ž─▒s─▒ eklemem gerekti─čine inan─▒yorum. Hatan─▒n k├Âkenini bilmek, yaz─▒l─▒mda neler olup bitti─čini anlamada yard─▒mc─▒ olabilir ve nihayetinde, bunun kayan nokta hatalar─▒n─▒n neden olu┼čtu─čunun ve zaman i├žinde birikmi┼č gibi g├Âr├╝nmesinin nedenlerini a├ž─▒klamaya yard─▒mc─▒ olaca─č─▒n─▒ umuyorum.

1. Genel Bak─▒┼č

Bir m├╝hendislik perspektifinden bak─▒ld─▒─č─▒nda, kayan nokta i┼člemlerinin ├žo─čunda bir hata unsuru olacakt─▒r ├ž├╝nk├╝ kayan nokta hesaplamalar─▒ yapan donan─▒m─▒n en son bir ├╝nitenin yar─▒s─▒ndan daha az bir hataya sahip olmas─▒ gerekir. Bu nedenle, ├žo─ču donan─▒m yaln─▒zca kayan nokta b├Âlmesinde ├Âzellikle sorunlu olan tek bir i┼člem i├žin son bir yerde bir birimin yar─▒s─▒ndan daha az bir hata vermesi gereken bir hassasiyette duracakt─▒r . Tek bir i┼člemi olu┼čturan ┼čey, ├╝nitenin ka├ž tane opera ald─▒─č─▒na ba─čl─▒d─▒r. ├ço─ču i├žin, iki, ancak baz─▒ birimler 3 veya daha fazla opera al─▒r. Bu nedenle, zaman i├žinde yap─▒lan hatalar nedeniyle tekrarlanan i┼člemlerin istenen bir hataya yol a├žaca─č─▒ garantisi yoktur.

2. Standartlar

├ço─ču i┼člemci IEEE-754 standard─▒n─▒ izler, ancak baz─▒lar─▒ normalle┼čtirilmi┼č veya farkl─▒ standartlar kullan─▒r. ├ľrne─čin, IEEE-754'te ├žok k├╝├ž├╝k kayan nokta say─▒lar─▒n─▒n hassasiyet pahas─▒na g├Âsterilmesine izin veren denormalize bir mod vard─▒r. Bununla birlikte, a┼ča─č─▒dakiler, tipik ├žal─▒┼čma modu olan normalle┼čtirilmi┼č IEEE-754 modunu kapsayacakt─▒r.

IEEE-754 standard─▒nda, donan─▒m tasar─▒mc─▒lar─▒na en son yerdeki bir ├╝nitenin yar─▒s─▒ndan daha az oldu─ču s├╝rece herhangi bir hata / epsilon de─čerine izin verilir ve sonu├ž, son b├Âl├╝mdeki bir ├╝nitenin yar─▒s─▒ndan daha az olmas─▒ gerekir. tek operasyon i├žin yer. Bu, tekrarlanan i┼člemler oldu─čunda neden hatalar─▒n topland─▒─č─▒n─▒ a├ž─▒klar. IEEE-754 ├žifte hassasiyet i├žin bu 54. bittir, ├ž├╝nk├╝ 53 bit, kayan nokta say─▒s─▒n─▒n (├Ârne─čin 5.3e5'teki 5.3) mantis olarak da adland─▒r─▒lan (normalize edilmi┼č) say─▒sal par├žay─▒ temsil etmek i├žin kullan─▒l─▒r. Sonraki b├Âl├╝mler, ├že┼čitli kayan nokta i┼člemlerinde donan─▒m hatas─▒n─▒n nedenleri hakk─▒nda daha ayr─▒nt─▒l─▒ bilgi vermektedir.

3. B├Âl├╝mdeki Yuvarlama hatas─▒n─▒n nedeni

Kayan nokta b├Âl├╝m├╝ndeki hatan─▒n ana nedeni b├Âl├╝m├╝ hesaplamak i├žin kullan─▒lan b├Âlme algoritmalar─▒d─▒r. Bir├žok bilgisayar sistemi esas olarak, bir ters ile ├žarpma ile b├Âlme hesaplamak Z=X/Y , Z = X * (1/Y) . Bir b├Âlme yinelemeli olarak hesaplan─▒r, yani her d├Âng├╝, IEEE-754 i├žin en sonda bir birimden daha az hatayla kar┼č─▒la┼č─▒lan herhangi bir ┼čey olan istenen kesinli─če ula┼č─▒l─▒ncaya kadar b├Âl├╝m├╝n baz─▒ bitlerini hesaplar. Y (1 / Y) 'nin kar┼č─▒l─▒kl─▒ giri┼č tablosu, yava┼č b├Âl├╝mdeki b├Âl├╝m se├žim tablosu (QST) olarak bilinir ve b├Âl├╝m se├žim ├žizelgesinin bit cinsinden b├╝y├╝kl├╝─č├╝, genellikle say─▒ taban─▒n─▒n geni┼čli─či veya bir dizi bit olur. b├Âl├╝m, her bir yinelemede hesaplanm─▒┼čt─▒r, ayr─▒ca bir ka├ž koruma bitidir. IEEE-754 standard─▒ i├žin, ├žift duyarl─▒kl─▒ (64 bit), b├Âl├╝c├╝n├╝n yar─▒ ├žap─▒n─▒n b├╝y├╝kl├╝─č├╝, art─▒ bir ka├ž koruma ucu k olacakt─▒r k>=2 . Bu nedenle, ├Ârne─čin, bir anda 2 bit hesaplayan bir b├Âl├╝c├╝ i├žin tipik bir B├Âl├╝m Se├žim Tablosu (say─▒ 4), 2+2= 4 bitler (art─▒ bir ka├ž iste─če ba─čl─▒ bit) olacakt─▒r.

3.1 B├Âlme Yuvarlama Hatas─▒: Kar┼č─▒l─▒kl─▒ Yakla┼č─▒m

B├Âl├╝m se├žim tablosunda kar┼č─▒l─▒k gelenler, b├Âlme y├Ântemine ba─čl─▒d─▒r : SRT b├Âlmesi gibi yava┼č b├Âlme veya Goldschmidt b├Âlmesi gibi h─▒zl─▒ b├Âlme; Her giri┼č, b├Âlme algoritmas─▒na g├Âre, m├╝mk├╝n olan en d├╝┼č├╝k hatay─▒ verme ├žabas─▒yla de─či┼čtirilir. Her hal├╝karda olsa da, t├╝m kar┼č─▒l─▒kl─▒ varl─▒klar , ger├žek kar┼č─▒tl─▒─č─▒n yakla┼č─▒klar─▒d─▒r ve baz─▒ hata ├Â─čelerini ortaya ├ž─▒kar─▒r. Hem yava┼č b├Âl├╝nme hem de h─▒zl─▒ b├Âlme y├Ântemleri, b├Âl├╝m├╝ yinelemeli olarak hesaplar, yani b├Âl├╝m├╝n baz─▒ bitleri her ad─▒mda hesaplan─▒r, daha sonra sonu├ž, temett├╝den ├ž─▒kar─▒l─▒r ve b├Âl├╝c├╝, hata b├Âlenin yar─▒s─▒ndan az olana kadar ad─▒mlar─▒ tekrarlar son yerde birim. Yava┼č b├Âlme y├Ântemleri, her ad─▒mda b├Âl├╝m├╝n sabit bir basama─č─▒n─▒ hesaplar ve genellikle in┼ča edilmesi daha d├╝┼č├╝k maliyetlidir ve h─▒zl─▒ b├Âlme y├Ântemleri, ad─▒m ba┼č─▒na de─či┼čken basamak say─▒s─▒n─▒ hesaplar ve genellikle yap─▒m─▒ daha pahal─▒d─▒r. B├Âlme y├Ântemlerinin en ├Ânemli k─▒sm─▒, ├žo─čunun bir kar┼č─▒l─▒kl─▒l─▒k yakla┼č─▒m─▒yla tekrarlanan ├žarpmalara dayanmas─▒d─▒r , bu y├╝zden hataya e─čilimlidirler.

4. Di─čer ─░┼člemlerde Yuvarlama Hatalar─▒: K─▒saltma

T├╝m i┼člemlerde yuvarlama hatalar─▒n─▒n bir ba┼čka nedeni, IEEE-754'├╝n izin verdi─či son cevab─▒n farkl─▒ kesilme modlar─▒d─▒r. Kesik, s─▒f─▒ra yuvarlak , s─▒f─▒ra en yak─▒n (varsay─▒lan), a┼ča─č─▒ yuvarlama ve yukar─▒ yuvarlama var. T├╝m y├Ântemler, tek bir i┼člem i├žin en son yerde bir ├╝niteden daha az hata unsuru sunar. Zaman i├žinde ve tekrarlanan i┼člemler s─▒ras─▒nda, kesme ayr─▒ca ortaya ├ž─▒kan hataya k├╝m├╝latif olarak da eklenir. Bu kesme hatas─▒, ├Âzellikle tekrar tekrar ├žarpman─▒n bir t├╝r├╝n├╝ i├žeren, ├╝stelimde sorunludur.

5. Tekrarlanan ─░┼člemler

Kayan nokta hesaplamalar─▒ yapan donan─▒m─▒n, sadece tek bir i┼člem i├žin son yerdeki bir birimin yar─▒s─▒ndan daha az bir hatayla sonu├ž vermesi gerekti─činden, izlenmedi─či takdirde hata tekrarlanan i┼člemlere g├Âre artacakt─▒r. Bu, s─▒n─▒rl─▒ bir hata gerektiren hesaplamalarda, matematik├žilerin IEEE-754'├╝n son yerine en yak─▒n tura en yak─▒n basama─č─▒ kullanma gibi y├Ântemleri kullanmas─▒n─▒n nedenidir , ├ž├╝nk├╝ zaman i├žinde hatalar─▒n birbirini iptal etmesi daha muhtemeldir. out ve Interval Aritmetik , yuvarlama hatalar─▒n─▒ tahmin etmek ve d├╝zeltmek i├žin IEEE 754 yuvarlama modlar─▒n─▒n varyasyonlar─▒yla birle┼čtirildi . Di─čer yuvarlama modlar─▒na k─▒yasla d├╝┼č├╝k g├Âreceli hatas─▒ nedeniyle, en yak─▒n d├╝z basama─ča (en son s─▒rada), IEEE-754'├╝n varsay─▒lan yuvarlama modudur.

Son yuvarlamada en yak─▒n d├╝z basama─ča kadar olan varsay─▒lan yuvarlama modunun, bir i┼člem i├žin son yerdeki bir birimin yar─▒s─▒ndan daha az bir hata garanti etti─čini unutmay─▒n. K─▒saltman─▒n kullan─▒lmas─▒, tek ba┼č─▒na yuvarlama ve tek ba┼č─▒na yuvarlama, son yerdeki bir birimin yar─▒s─▒ndan b├╝y├╝k, ancak son yerdeki bir ├╝niteden daha az bir hataya neden olabilir; Aral─▒k Aritmetrisinde kullan─▒l─▒r.

6. ├ľzet

K─▒sacas─▒, kayan nokta operasyonlar─▒ndaki hatalar─▒n temel nedeni, donan─▒mdaki kesilmenin ve b├Âl├╝nme durumunda kar┼č─▒l─▒kl─▒ kesmenin kesilmesidir. IEEE-754 standard─▒, tek bir i┼člem i├žin son bir yerde yaln─▒zca bir birimin yar─▒s─▒ndan daha az bir hata gerektirdi─činden, tekrarlanan i┼člemler ├╝zerindeki kayan nokta hatalar─▒ d├╝zeltilmedi─či s├╝rece eklenecektir.


576







.1 veya 1/10'u taban 2'ye (ikili) d├Ân├╝┼čt├╝rd├╝─č├╝n├╝zde, ondal─▒k noktadan sonra yinelenen bir d├╝zen elde edersiniz, t─▒pk─▒ 10'da 1/3 g├Âstermeye ├žal─▒┼č─▒r gibi de─čer tam de─čildir ve bu nedenle yapamazs─▒n─▒z. normal kayan nokta y├Ântemlerini kullanarak bununla tam matematik.


434







Buradaki cevaplar─▒n ├žo─ču bu soruyu ├žok kuru ve teknik olarak ele almaktad─▒r. Bunu normal insan─▒n anlayabilece─či ┼čekilde ele almak isterim.

Pizza dilimlemeye ├žal─▒┼čt─▒─č─▒n─▒z─▒ hayal edin. Pizza dilimlerini tam olarak ikiye b├Âlen robot bir pizza kesiciniz var . B├╝t├╝n bir pizzay─▒ yar─▒ya indirebilir ya da mevcut bir dilimi yar─▒ya indirebilir, ancak her durumda yar─▒ya da daima ayn─▒ olur.

Bu pizza kesicinin ├žok iyi hareketleri var ve e─čer b├╝t├╝n bir pizzayla ba┼člarsan─▒z, o zaman ikiye b├Âl├╝n ve en k├╝├ž├╝k dilimi yar─▒ya indirmeye devam ederseniz , dilimin y├╝ksek hassasiyetli yetenekleri i├žin bile ├žok k├╝├ž├╝k olana kadar yar─▒ya 53 kez yapabilirsiniz. . Bu noktada, art─▒k ├žok ince bir dilimi yar─▒ya ├ž─▒karamazs─▒n─▒z, ancak oldu─ču gibi i├žermeli veya hari├ž tutmal─▒s─▒n─▒z.

┼×imdi t├╝m dilimleri, onda birine (0.1) veya be┼čte birine (0.2) kadar pizza ekleyebilecek ┼čekilde nas─▒l par├žalars─▒n─▒z? Ger├žekten d├╝┼č├╝n ve ├žal─▒┼čmay─▒ dene. Elinizde efsanevi bir hassas pizza kesiciniz varsa, ger├žek bir pizza kullanmay─▒ da deneyebilirsiniz. :-)


En deneyimli programc─▒lar, tabii ki, birlikte par├žas─▒na hi├žbir ┼čekilde bir olmas─▒d─▒r ger├žek yan─▒t─▒, biliyorum tam onuncu ya da be┼činci pizza olursa olsun onlar─▒ dilim nas─▒l ince, bu dilimleri kullanarak. Olduk├ža iyi bir yakla┼čt─▒rma yapabilirsiniz ve 0,1 yakla┼č─▒m─▒yla 0,2 yakla┼č─▒m─▒ eklerseniz, 0,3 ile olduk├ža iyi bir yakla┼č─▒ma sahip olursunuz, ama yine de bu sadece bir yakla┼č─▒md─▒r.

├çift duyarl─▒kl─▒ say─▒lar i├žin (pizzan─▒z─▒ 53 kez yar─▒ya alman─▒za izin veren hassasiyettir), 0,1'den az ve daha b├╝y├╝k say─▒lar 0,09999999999999999167332731531132594682276248931884765625 ve 0,1000000000000000055551115123125782702118151550400000000555511151231257827021181515454544533035015750345650650650650650650650750650650650650650650449494949494934913493506506506506506506506157503506506506506257503 ve 449. Sonuncusu ├Âncekinden 0.1'e biraz daha yak─▒nd─▒r, bu nedenle say─▒sal bir ayr─▒┼čt─▒r─▒c─▒, 0.1 girdisi verildi─činde ikincisini lehine ├ževirir.

(Bu iki say─▒ aras─▒ndaki fark, ya yukar─▒ do─čru bir ├Ânyarg─▒ya neden olan ya da a┼ča─č─▒ do─čru bir ├Ânyarg─▒ya neden olan hari├ž tutmaya karar vermemiz gereken en k├╝├ž├╝k dilimdir. Bu en k├╝├ž├╝k dilim i├žin teknik terim ulp'tir .)

0.2 durumunda, say─▒lar tamamen ayn─▒d─▒r, sadece 2 kat ├Âl├žeklenir. Yine, 0.2'den biraz y├╝ksek olan de─čeri tercih ederiz.

Her iki durumda da, 0,1 ve 0,2 i├žin olan de─čerlerin hafif bir yukar─▒ e─čilime sahip oldu─čuna dikkat edin. Bu ├Ânyarg─▒lar─▒ yeterince eklersek, say─▒y─▒ istedi─čimizden daha ileri ve uza─ča iteceklerdir, ve asl─▒nda 0,1 + 0,2 olmas─▒ durumunda, ├Ânyarg─▒, ortaya ├ž─▒kan say─▒ art─▒k en yak─▒n say─▒ olmayacak kadar y├╝ksek olacakt─▒r. 0.3.

├ľzellikle, 0,199999999999999919191919191919191919191919191919191419191919191719: 1973: 1978.


Not: Baz─▒ programlama dilleri, dilimleri tam onda birine b├Âlen pizza kesicileri de sa─člar . Her ne kadar bu t├╝r pizza kesiciler nadir olsa da, birine eri┼čiminiz varsa, bir dilimin tam olarak onda biri veya be┼čte birini alabilmeniz ├Ânemlidir.

(Aslen Quora'da yay─▒nlanm─▒┼čt─▒r.)


284







Kayan nokta yuvarlama hatalar─▒. 0,1, ├╝s-10'da, 5-eksik asal ├žarpan─▒ nedeniyle taban-10'da oldu─ču gibi do─čru g├Âsterilemez. 1/3 gibi, ondal─▒k say─▒da temsil etmek i├žin sonsuz say─▒da basamak al─▒r, ancak taban-3'te "0.1" olur. 0,1, ├╝s-2ÔÇÖde sonsuz say─▒daki basama─č─▒ al─▒r, burada ├╝s-10ÔÇÖda de─čildir. Bilgisayarlar─▒n da sonsuz miktarda belle─či yok.


207







Di─čer do─čru cevaplara ek olarak, kayan nokta aritmeti─čiyle ilgili problemleri ├Ânlemek i├žin de─čerlerinizi ├Âl├žeklendirmeyi d├╝┼č├╝nebilirsiniz.

├ľrne─čin:

 var result = 1.0 + 2.0;     // result === 3.0 returns true
 

... yerine:

 var result = 0.1 + 0.2;     // result === 0.3 returns false
 

─░fade JavaScript'te 0.1 + 0.2 === 0.3 geri d├Âner false , ancak neyse ki kayan noktadaki tamsay─▒ aritmeti─či kesindir, bu nedenle ondal─▒k g├Âsterim hatalar─▒ndan ├Âl├žeklendirme ile ka├ž─▒n─▒labilir.

Pratik bir ├Ârnek olarak, do─črulu─čun en ├Ânemli oldu─ču kayan nokta sorunlar─▒ndan ka├ž─▒nmak i├žin, paray─▒ sent say─▒s─▒n─▒ temsil eden bir tamsay─▒ olarak ele alman─▒z ├Ânerilir: 1 dolar 2550 yerine sent 25.50 .


1 Douglas Crockford: JavaScript: ─░yi Par├žalar : Ek A - K├Ât├╝ Par├žalar (sayfa 105) .


117







Cevab─▒m olduk├ža uzun, bu y├╝zden ├╝├ž b├Âl├╝me ay─▒rd─▒m. Soru kayan nokta matemati─či ile ilgili oldu─ču i├žin, makinenin ger├žekte ne yapt─▒─č─▒n─▒ vurgulad─▒m. Ayr─▒ca ├žift (64 bit) hassasiyete ├Âzg├╝ yapt─▒m, ancak arg├╝man herhangi bir kayan nokta aritmeti─čine e┼čit olarak uygulan─▒r.

├Âns├Âz

Bir IEEE 754 ├žift duyarl─▒kl─▒ ikili kayan nokta format─▒ (ikili64) numaras─▒, formun bir say─▒s─▒n─▒ temsil eder.

de─čer = (-1) ^ s * (1. m 51 m 50 ... m 2 m 1 m 0 ) 2 * 2 e-1023

64 bit i├žinde:

  • ─░lk bit i┼čaret bitidir : 1 say─▒ negatifse, 0 aksi takdirde 1 .
  • Bir sonraki 11 bit olan ├╝s olup, ofset Di─čer bir deyi┼čle 1023 ile, bir ├žift duyarl─▒kl─▒ numaras─▒ndan ├╝stel bit okuduktan sonra 1023 iki g├╝├ž elde edilmesi i├žin ├ž─▒kart─▒lmas─▒ gerekmektedir.
  • Kalan 52 bit, anlaml─▒ (veya mantis). Mantiste olarak, bir 'ima' 1. her zaman 2 herhangi bir ikili de─čerin en ├Ânemli bit oldu─čundan ihmal 1 .

1 - IEEE 754 imzal─▒ s─▒f─▒r konseptine izin verir - +0 ve -0 farkl─▒ ┼čekilde ele al─▒n─▒r: 1 / (+0) pozitif sonsuzdur; 1 / (-0) negatif sonsuzdur. S─▒f─▒r de─čerler i├žin, mantis ve ├╝s bitlerinin t├╝m├╝ s─▒f─▒rd─▒r. Not: s─▒f─▒r de─čerleri (+0 ve -0) a├ž─▒k├ža denormal 2 olarak s─▒n─▒fland─▒r─▒lmam─▒┼čt─▒r .

2 - Bu, ofset s─▒f─▒r─▒ s─▒f─▒r (ve ima edilen ) olan denormal say─▒lar i├žin ge├žerli de─čildir 0. . Denormal ├žift hassasiyetli say─▒ aral─▒─č─▒ d dak ÔëĄ | x | Min d max , burada d dak (temsil edilebilecek en k├╝├ž├╝k s─▒f─▒r say─▒) 2 -1023 - 51 (Ôëł 4.94 x 10 -324 ) ve d max ( mantinin tamamen 1 s'den olu┼čtu─ču en b├╝y├╝k denormal say─▒ ) 2 + 1 - 2 - 1023 - 51 (Ôëł 2.225 x 10 - 308 ).


├çift duyarl─▒kl─▒ bir say─▒n─▒n ikiliye ├ževrilmesi

├çift duyarl─▒kl─▒ kayan nokta say─▒s─▒n─▒ ikiliye d├Ân├╝┼čt├╝rmek i├žin pek ├žok ├ževrimi├ži d├Ân├╝┼čt├╝r├╝c├╝ vard─▒r (├Ârne─čin binaryconvert.com'da ), ancak burada IEEE 754 g├Âsterimini ├žift duyarl─▒kl─▒ bir say─▒ i├žin elde etmek i├žin baz─▒ ├Ârnek C # kodu verilmi┼čtir (├╝├ž par├žay─▒ s├╝tunlarla ay─▒r─▒r─▒m ( : ). :

 public static string BinaryRepresentation(double value)
{
    long valueInLongType = BitConverter.DoubleToInt64Bits(value);
    string bits = Convert.ToString(valueInLongType, 2);
    string leadingZeros = new string('0', 64 - bits.Length);
    string binaryRepresentation = leadingZeros + bits;

    string sign = binaryRepresentation[0].ToString();
    string exponent = binaryRepresentation.Substring(1, 11);
    string mantissa = binaryRepresentation.Substring(12);

    return string.Format("{0}:{1}:{2}", sign, exponent, mantissa);
}
 

Konuya gelmek: Orijinal soru

(TL i├žin alt─▒na atla; DR s├╝r├╝m├╝)

Cato Johnston (soru soran) neden 0.1 + 0.2! = 0.3 oldu─čunu sordu.

─░kili olarak yaz─▒lm─▒┼čt─▒r (├╝├ž par├žay─▒ ay─▒ran iki nokta ile), de─čerlerin IEEE 754 g├Âsterimleri:

 0.1 => 0:01111111011:1001100110011001100110011001100110011001100110011010
0.2 => 0:01111111100:1001100110011001100110011001100110011001100110011010
 

Mantis, yinelenen rakamlardan olu┼čtu─čunu unutmay─▒n 0011 . Bu anahtar 0.1, 0.2 ve 0.3, ikili temsil edilemez - hesaplamalar i├žin bir hata vard─▒r neden tam bir de sonlu tam temsil edilebilir herhangi bir ikili bit say─▒s─▒ fazla 1/9, 1/3 veya 1/7 ondal─▒k basamak .

Ayr─▒ca, ├╝s i├žindeki g├╝c├╝ 52 oran─▒nda azaltabilece─čimizi ve ikili g├Âsterimdeki noktay─▒ sa─ča do─čru 52 yer de─či┼čtirebilece─čimize dikkat edin (10 -3 * 1.23 == 10 -5 * 123 gibi). Bu daha sonra ikili g├Âsterimi a * 2 p bi├žiminde temsil etti─či tam de─čer olarak g├Âstermemizi sa─člar . 'a' bir tamsay─▒d─▒r.

├ťstleri ondal─▒k basama─ča d├Ân├╝┼čt├╝rmek, ofseti ├ž─▒karmak ve ima 1 edilenleri (k├Â┼čeli parantez i├žinde) yeniden eklemek , 0,1 ve 0,2 ┼čunlard─▒r:

 0.1 => 2^-4 * [1].1001100110011001100110011001100110011001100110011010
0.2 => 2^-3 * [1].1001100110011001100110011001100110011001100110011010
or
0.1 => 2^-56 * 7205759403792794 = 0.1000000000000000055511151231257827021181583404541015625
0.2 => 2^-55 * 7205759403792794 = 0.200000000000000011102230246251565404236316680908203125
 

─░ki say─▒ eklemek i├žin, ├╝s, ayn─▒ olmal─▒d─▒r, yani:

 0.1 => 2^-3 *  0.1100110011001100110011001100110011001100110011001101(0)
0.2 => 2^-3 *  1.1001100110011001100110011001100110011001100110011010
sum =  2^-3 * 10.0110011001100110011001100110011001100110011001100111
or
0.1 => 2^-55 * 3602879701896397  = 0.1000000000000000055511151231257827021181583404541015625
0.2 => 2^-55 * 7205759403792794  = 0.200000000000000011102230246251565404236316680908203125
sum =  2^-55 * 10808639105689191 = 0.3000000000000000166533453693773481063544750213623046875
 

Toplam 2 n * 1 formunda olmad─▒─č─▒ i├žin {bbb} ├╝ss├╝ birer birer art─▒r─▒r ve elde etmek i├žin ondal─▒k ( ikili ) noktas─▒n─▒ de─či┼čtiririz:

 sum = 2^-2  * 1.0011001100110011001100110011001100110011001100110011(1)
    = 2^-54 * 5404319552844595.5 = 0.3000000000000000166533453693773481063544750213623046875
 

┼×imdi mantisede 53 bit vard─▒r (53. sat─▒r yukar─▒daki k├Â┼čeli parantez i├žindedir). IEEE 754 i├žin varsay─▒lan yuvarlama modu ' Yuvarlaktan En Yak─▒n'a' d─▒r - yani, x say─▒s─▒ a ve b aras─▒nda bir de─čere d├╝┼čerse , en az anlaml─▒ bitin s─▒f─▒r oldu─ču de─čer se├žilir.

 a = 2^-54 * 5404319552844595 = 0.299999999999999988897769753748434595763683319091796875
  = 2^-2  * 1.0011001100110011001100110011001100110011001100110011

x = 2^-2  * 1.0011001100110011001100110011001100110011001100110011(1)

b = 2^-2  * 1.0011001100110011001100110011001100110011001100110100
  = 2^-54 * 5404319552844596 = 0.3000000000000000444089209850062616169452667236328125
 

A ve b'nin yaln─▒zca son bitde farkl─▒ oldu─čunu unutmay─▒n ; ...0011 + 1 = ...0100 . Bu durumda, en az anlaml─▒ bit de─čerine sahip olan de─čer b , yani toplam:

 sum = 2^-2  * 1.0011001100110011001100110011001100110011001100110100
    = 2^-54 * 5404319552844596 = 0.3000000000000000444089209850062616169452667236328125
 

0.3'├╝n ikili g├Âsterimi ise:

 0.3 => 2^-2  * 1.0011001100110011001100110011001100110011001100110011
    =  2^-54 * 5404319552844595 = 0.299999999999999988897769753748434595763683319091796875
 

bu, yaln─▒zca 0,1 ve 0,2 ile 2 -54 aras─▒ndaki toplam─▒n ikili g├Âsteriminden farkl─▒d─▒r .

0.1 ve 0.2'nin ikili g├Âsterimi, IEEE 754 taraf─▒ndan izin verilen say─▒lar─▒n en do─čru g├Âsterimleridir. Bu g├Âsterimin, varsay─▒lan yuvarlama moduna ba─čl─▒ olarak eklenmesi, sadece en az anlaml─▒ bite farkl─▒l─▒k g├Âsteren bir de─čere yol a├žar.

TL; DR

0.1 + 0.2 Bir IEEE 754 ikili g├Âstergesine yazma (├╝├ž par├žay─▒ ay─▒ran iki nokta ile) ve bunu kar┼č─▒la┼čt─▒rarak 0.3 ┼č├Âyledir (belirgin bitleri k├Â┼čeli ayra├ž i├žine koyuyorum):

 0.1 + 0.2 => 0:01111111101:0011001100110011001100110011001100110011001100110[100]
0.3       => 0:01111111101:0011001100110011001100110011001100110011001100110[011]
 

Ondal─▒k basama─ča d├Ân├╝┼čt├╝r├╝len bu de─čerler:

 0.1 + 0.2 => 0.300000000000000044408920985006...
0.3       => 0.299999999999999988897769753748...
 

Fark tam olarak 2 -54 5,5511151231258 x 10 ~ olan -17 orijinal de─čerlerine g├Âre anlaml─▒ (bir ├žok uygulama i├žin) -.

Kayan nokta say─▒s─▒n─▒n son birka├ž bitini kar┼č─▒la┼čt─▒rmak do─čal olarak tehlikelidir, ├ž├╝nk├╝ ├╝nl├╝ " Her Bilgisayar Bilim Adam─▒n─▒n Kayan Nokta Aritmeti─či Hakk─▒nda Bilmeniz Gerekenler " (bu cevab─▒n t├╝m b├Âl├╝mlerini kapsayan) yazan herkes bilecektir.

├ço─ču hesap makinesi , bu problemi ├ž├Âzmek i├žin ek koruma rakamlar─▒ kullan─▒r, ki bu ┼ču 0.1 + 0.2 ┼čekilde verir 0.3 : son birka├ž bit yuvarlan─▒r.


100







Bilgisayarda depolanan kayan nokta say─▒lar─▒ iki b├Âl├╝mden olu┼čur; bir tam say─▒ ve taban─▒n tam say─▒ taraf─▒ndan al─▒nd─▒─č─▒ ve ├žarp─▒ld─▒─č─▒ bir ├╝s.

Bilgisayar 10 ├╝ss├╝nde ├žal─▒┼č─▒yor 0.1 olsayd─▒ 1 x 10Ôü╗┬╣ , 0.2 olurdu , olurdu 2 x 10Ôü╗┬╣ ve 0.3 olurdu 3 x 10Ôü╗┬╣ . Tamsay─▒ matemati─či kolay ve kesindir, dolay─▒s─▒yla ekleme 0.1 + 0.2 a├ž─▒k├ža sonu├žlanacakt─▒r 0.3 .

├ľrnek i├žin genellikle 10 taban─▒na ├žal─▒┼čmayan bilgisayarlar, onlar, sen hala baz─▒ de─čerler i├žin kesin sonu├žlar alabilirsiniz taban─▒ndaki 2 ├žal─▒┼čmak 0.5 oldu─čunu 1 x 2Ôü╗┬╣ ve 0.25 oldu─čunu 1 x 2Ôü╗┬▓ ve bunlar─▒ ekleyerek sonu├žlan─▒r 3 x 2Ôü╗┬▓ ya 0.75 . Kesinlikle.

Sorun, tam olarak 10. basamakta g├Âsterilebilecek, ancak 2. basamakta g├Âsterilemeyen say─▒larla ortaya ├ž─▒kmaktad─▒r. Bu say─▒lar en yak─▒n de─čerlerine yuvarlanmal─▒d─▒r. ├çok yayg─▒n IEEE 64-bit kayan noktal─▒ bi├žimi, en yak─▒n numaray─▒ varsayarsak 0.1 oldu─čunu 3602879701896397 x 2Ôü╗ÔüÁÔüÁ ve en yak─▒n say─▒ 0.2 oldu─ču 7205759403792794 x 2Ôü╗ÔüÁÔüÁ ; Bunlar─▒ bir araya getirmek 10808639105689191 x 2Ôü╗ÔüÁÔüÁ , ya da tam bir ondal─▒k de─čerle sonu├žlan─▒r 0.3000000000000000444089209850062616169452667236328125 . Kayan nokta numaralar─▒ genellikle g├Âsterim i├žin yuvarlan─▒r.


55







Kayan nokta yuvarlama hatas─▒. G├Ânderen Ne Her Bilgisayar M├╝hendisi gerekti─čini biliyorum Kayan Noktal─▒ Aritmetik Hakk─▒nda :

S─▒n─▒rs─▒z say─▒da bitin sonsuz say─▒da ger├žek say─▒n─▒n s─▒k─▒┼čt─▒r─▒lmas─▒ yakla┼č─▒k bir g├Âsterim gerektirir. S─▒n─▒rs─▒z say─▒da tam say─▒ olmas─▒na ra─čmen, ├žo─ču programda tam say─▒ hesaplamalar─▒ sonucu 32 bit olarak saklanabilir. Buna kar┼č─▒l─▒k, herhangi bir sabit say─▒da bit verildi─činde, ger├žek say─▒larla yap─▒lan ├žo─ču hesaplama, bu kadar ├žok bit kullan─▒larak tam olarak temsil edilemeyen miktarlar ├╝retecektir. Bu nedenle, kayan nokta hesaplamas─▒n─▒n sonucu, sonlu temsiline uymas─▒ i├žin s─▒kl─▒kla yuvarlat─▒lmal─▒d─▒r. Bu yuvarlama hatas─▒, kayan nokta hesaplamas─▒n─▒n karakteristik ├Âzelli─čidir.


46







Ge├žici ├ž├Âz├╝m├╝m:

 function add(a, b, precision) {
    var x = Math.pow(10, precision || 2);
    return (Math.round(a * x) + Math.round(b * x)) / x;
}
 

hassasiyet , ekleme s─▒ras─▒nda ondal─▒k basama─č─▒n ard─▒ndan korumak istedi─činiz basamak say─▒s─▒n─▒ belirtir.


33







Bir├žok iyi cevap g├Ânderildi, ancak bir tane daha eklemek istiyorum.

T├╝m say─▒lar ile temsil edilebilir de─čil y├╝zer / ├žiftler ├ľrne─čin, say─▒ "0.2" IEEE-754 ┼čamand─▒ra noktas─▒ standart bir hassas ",200000003" olarak temsil edilecektir.

Kaputun alt─▒ndaki ger├žek say─▒lar─▒n depolanmas─▒ i├žin model, ┼čamand─▒ra numaralar─▒n─▒ a┼ča─č─▒daki gibi g├Âsterir.


g├Âr├╝nt├╝ tan─▒m─▒n─▒ buraya girin

E─čer yazabilirsiniz ra─čmen 0.2 kolayca FLT_RADIX ve DBL_RADIX 2'dir; "─░kili Kayan Noktal─▒ Aritmetik i├žin IEEE Standard─▒ (ISO / IEEE Std 754-1985)" kullanan FPU'lu bir bilgisayar i├žin 10 de─čil.

Bu y├╝zden bu rakamlar─▒ tam olarak g├Âstermek biraz zor. Bu de─či┼čkeni herhangi bir ara hesaplama olmadan a├ž─▒k├ža belirtseniz bile.


29







Bu ├╝nl├╝ ├žifte kesinlik sorusu ile ilgili baz─▒ istatistikler.

T├╝m de─čerleri ( a + b ) 0,1 (0,1 ile 100 aras─▒nda) ad─▒m─▒n─▒ kullanarak eklerken , ~% 15 hassasiyet hatas─▒ ┼čans─▒m─▒z vard─▒r . Hatan─▒n biraz daha b├╝y├╝k veya daha k├╝├ž├╝k de─čerlere yol a├žabilece─čini unutmay─▒n. ─░┼čte baz─▒ ├Ârnekler:

 0.1 + 0.2 = 0.30000000000000004 (BIGGER)
0.1 + 0.7 = 0.7999999999999999 (SMALLER)
...
1.7 + 1.9 = 3.5999999999999996 (SMALLER)
1.7 + 2.2 = 3.9000000000000004 (BIGGER)
...
3.2 + 3.6 = 6.800000000000001 (BIGGER)
3.2 + 4.4 = 7.6000000000000005 (BIGGER)
 

T├╝m de─čerleri ( a - b burada a> b ) 0.1 ad─▒m─▒n─▒ kullanarak (100'den 0.1'e kadar) ├ž─▒kar─▒rken ~% 34 hassasiyet hatas─▒ ┼čans─▒m─▒z vard─▒r . ─░┼čte baz─▒ ├Ârnekler:

 0.6 - 0.2 = 0.39999999999999997 (SMALLER)
0.5 - 0.4 = 0.09999999999999998 (SMALLER)
...
2.1 - 0.2 = 1.9000000000000001 (BIGGER)
2.0 - 1.9 = 0.10000000000000009 (BIGGER)
...
100 - 99.9 = 0.09999999999999432 (SMALLER)
100 - 99.8 = 0.20000000000000284 (BIGGER)
 

*% 15 ve% 34 ger├žekten ├žok b├╝y├╝k, bu y├╝zden hassasiyet ├žok ├Ânemliyken daima BigDecimal kullan─▒n. 2 ondal─▒k basamakta (ad─▒m 0.01) durum biraz daha k├Ât├╝le┼čir (% 18 ve% 36).


28







Hay─▒r, k─▒r─▒k de─čil, fakat ondal─▒k kesirlerin ├žo─čuna yakla┼č─▒lmal─▒d─▒r

├Âzet

Kayan noktal─▒ aritmetik oldu─čunu s─▒k s─▒k bunu biraz biz ne yazd─▒ gelen kapal─▒ girdi veriyoruz d─▒┼čar─▒ o d├Ânmesini sa─člay─▒n kesin, ne yaz─▒k ki, bizim her zamanki 10 tabanl─▒ say─▒ g├Âsterimi ile iyi yukar─▒ya uyu┼čmuyor.

0.01, 0.02, 0.03, 0.04 ... 0.24 gibi basit say─▒lar bile tam olarak ikili kesirler olarak g├Âsterilemez. E─čer 0.01, .02, .03 ... sayarsan─▒z, 0.25'e ula┼čana kadar olmazsa, temel 2'de temsil edilebilecek ilk k─▒sm─▒ elde edersiniz . FP kullanarak denemeyi denediyseniz, 0.01'iniz biraz kapal─▒ olurdu, bu y├╝zden 25 tanesini g├╝zel bir tam 0.25 de─čerine eklemenin tek yolu, koruyucu u├žlar─▒ ve yuvarlamay─▒ i├žeren uzun bir nedensellik zincirini gerektiriyordu. Tahmin etmek zor, bu y├╝zden ellerimizi f─▒rlat─▒p "FP tam olmayan" diyoruz , ama bu do─čru de─čil.

S├╝rekli olarak FP donan─▒m─▒na taban 10'da basit g├Âr├╝nen, ancak taban 2'deki yinelenen bir kesir olan bir ┼čey veriyoruz.

Bu nas─▒l oldu?

Ondal─▒k yazd─▒─č─▒m─▒zda, her kesir (├Âzellikle, her sonland─▒r─▒c─▒ ondal─▒k) , formun rasyonel bir say─▒s─▒d─▒r.

           a / (2 n x 5 m )

─░kili, biz sadece almak 2 n terimini, yani:

           a / 2 n

O halde ondal─▒kta 1 / 3'├╝ temsil edemeyiz . Taban 10 birinci s─▒n─▒f bir fakt├Âr olarak 2 i├žerdi─činden, bir ikili kesir olarak yazabilir her say─▒ da bir taban 10 kesir olarak yaz─▒labilir. Bununla birlikte, 10 baz fraksiyonu olarak yazd─▒─č─▒m─▒z neredeyse hi├žbir ┼čey ikili olarak g├Âsterilemez. 0.01, 0.02, 0.03 ... 0.99 aral─▒─č─▒nda, FP bi├žimimizde sadece ├╝├ž say─▒ g├Âsterilebilir: 0.25, 0.50 ve 0.75, ├ž├╝nk├╝ bunlar 1/4, 1/2 ve 3/4, t├╝m say─▒lar Sadece 2 n terimini kullanan bir asal ├žarpan ile .

10 ├╝ss├╝nde 1 / 3'├╝ temsil edemiyoruz . Ama ikili, biz yapamay─▒z 1 / 10 veya 1 / 3 .

Bu nedenle, her ikili fraksiyon ondal─▒k olarak yaz─▒labilse de, tersi do─čru de─čildir. Ve asl─▒nda, ondal─▒k kesirlerin ├žo─ču ikili olarak tekrarlan─▒r.

Bununla ba┼ča ├ž─▒kmak

Geli┼čtiricilere genellikle <epsilon kar┼č─▒la┼čt─▒rmalar─▒ yapmalar─▒ s├Âylenir, daha iyi tavsiye integral de─čerlerini yuvarlamak olabilir (C k├╝t├╝phanesinde: round () ve roundf (), yani, FP format─▒nda kal─▒r) ve sonra kar┼č─▒la┼čt─▒r─▒rs─▒n─▒z. Belirli bir ondal─▒k kesir uzunlu─čuna yuvarlama, ├ž─▒kt─▒yla ilgili ├žo─ču sorunu ├ž├Âzer.

Ayr─▒ca, ger├žek say─▒-s─▒kma problemlerinde (FP'nin erken, korkutucu pahal─▒ bilgisayarlarda icat etti─či problemler) evrenin fiziksel sabitleri ve di─čer t├╝m ├Âl├ž├╝mler sadece g├Âreceli olarak ├žok az say─▒da ├Ânemli rakamlar taraf─▒ndan bilinir, yani t├╝m problem alan─▒ Zaten "tam" idi. FP "kesinlik" bu t├╝r uygulamalarda sorun de─čildir.

B├╝t├╝n mesele, insanlar fasulyenin say─▒m─▒ i├žin FP kullanmaya ├žal─▒┼čt─▒klar─▒nda ortaya ├ž─▒k─▒yor. Bunun i├žin ├žal─▒┼č─▒r, ancak yaln─▒zca integral de─čerlere sad─▒k kal─▒rsan─▒z, hangi t├╝rden onu kullanma noktas─▒n─▒ yitirirse. ─░┼čte bu y├╝zden b├╝t├╝n bu ondal─▒k kesir yaz─▒l─▒m k├╝t├╝phanelerine sahibiz.

Chris'in Pizza cevab─▒n─▒ ├žok seviyorum , ├ž├╝nk├╝ as─▒l sorunu a├ž─▒kl─▒yor, sadece "yanl─▒┼čl─▒k" ile ilgili her zamanki el dalgas─▒ de─čil. E─čer FP basit├že "yanl─▒┼č" olsayd─▒, bunu d├╝zeltebilirdik ve on y─▒llar ├Ânce yapard─▒k . Yapmamam─▒z─▒n nedeni, FP format─▒n─▒n kompakt ve h─▒zl─▒ olmas─▒ ve ├žok say─▒da rakam─▒ s─▒k─▒┼čt─▒rman─▒n en iyi yoludur. Ayr─▒ca, uzay ├ža─č─▒ ve silahlanma yar─▒┼č─▒n─▒n bir miras─▒ ve k├╝├ž├╝k bellek sistemlerini kullanan ├žok yava┼č bilgisayarlarla b├╝y├╝k sorunlar─▒ ├ž├Âzme giri┼čimlerinin erken. (Bazen, 1 bit depolama i├žin ayr─▒ ayr─▒ manyetik ├žekirdekler , ancak bu ba┼čka bir hikaye. )

Sonu├ž

E─čer bir bankada sadece fasulye say─▒yorsan─▒z, ilk olarak ondal─▒k basamakl─▒ g├Âsterimler kullanan yaz─▒l─▒m ├ž├Âz├╝mleri m├╝kemmel sonu├ž verir. Fakat kuantum kromodinami─čini veya aerodinami─či bu ┼čekilde yapamazs─▒n─▒z.


26







Koli band─▒ ├ž├Âz├╝m├╝n├╝ denedin mi?

Hatalar─▒n ne zaman ortaya ├ž─▒kt─▒─č─▒n─▒ belirlemeye ├žal─▒┼č─▒n ve ifadeler k─▒sasa d├╝zeltin, sorun de─čil ama baz─▒ problemler i├žin tek ├ž├Âz├╝m budur ve bunlardan biridir.

  if( (n * 0.1) < 100.0 ) { return n * 0.1 - 0.000000000000001 ;}
                    else { return n * 0.1 + 0.000000000000001 ;}    
 

Ayn─▒ problemi c # 'daki bir bilimsel sim├╝lasyon projesinde ya┼čad─▒m ve size kelebek etkisini g├Âz ard─▒ ederseniz bunun ┼či┼čman bir ejderhaya d├Ân├╝┼čece─čini ve sizi a.


19







En iyi ├ž├Âz├╝m├╝ sunmak i├žin A┼ča─č─▒daki y├Ântemi ke┼čfetti─čimi s├Âyleyebilirim:

 parseFloat((0.1 + 0.2).toFixed(10)) => Will return 0.3
 

Bunun neden en iyi ├ž├Âz├╝m oldu─čunu a├ž─▒klamama izin verin. Yukar─▒da verilen di─čer cevaplarda da belirtildi─či gibi, sorunu ├ž├Âzmek i├žin Javascript toFixed () i┼člevini kullanmaya haz─▒r kullanmak iyi bir fikirdir. Fakat b├╝y├╝k ihtimalle baz─▒ problemlerle kar┼č─▒la┼čacaks─▒n─▒z.

E─čer gibi iki ┼čamand─▒ra say─▒lar─▒ toplamak i├žin gidiyoruz d├╝┼č├╝n├╝n 0.2 ve 0.7 i┼čte burada: 0.2 + 0.7 = 0.8999999999999999 .

Bekledi─činiz sonu├ž, 0.9 bu durumda 1 basamakl─▒ hassasiyetle bir sonuca ihtiyac─▒n─▒z oldu─ču anlam─▒na geliyordu. Bu y├╝zden kullanmal─▒yd─▒n, (0.2 + 0.7).tofixed(1) ama verilen say─▒ya ba─čl─▒ oldu─ču i├žin toFixed () 'a sadece belirli bir parametre veremezsin.

 `0.22 + 0.7 = 0.9199999999999999`
 

Bu ├Ârnekte 2 basamak hassasiyetine ihtiyac─▒n─▒z vard─▒r toFixed(2) , bu y├╝zden olmas─▒ gerekir , bu nedenle verilen her bir ┼čamand─▒ra numaras─▒na uymas─▒ gereken paragraf ne olmal─▒d─▒r?

├ľyleyse her durumda 10 olsun.

 (0.2 + 0.7).toFixed(10) => Result will be "0.9000000000"
 

Lanet olsun! 9'dan sonra bu istenmeyen s─▒f─▒rlarla ne yapacaks─▒n? ─░stedi─činiz gibi yapmak i├žin y├╝zmeye ├ževirme zaman─▒:

 parseFloat((0.2 + 0.7).toFixed(10)) => Result will be 0.9
 

┼×imdi ├ž├Âz├╝m├╝ buldu─čunuza g├Âre, bunun gibi bir i┼člev olarak ├Ânermek daha iyidir:

 function floatify(number){
           return parseFloat((number).toFixed(10));
        }
 

Hadi kendin deneyelim:

 function floatify(number){
       return parseFloat((number).toFixed(10));
    }
 
function addUp(){
  var number1 = +$("#number1").val();
  var number2 = +$("#number2").val();
  var unexpectedResult = number1 + number2;
  var expectedResult = floatify(number1 + number2);
  $("#unexpectedResult").text(unexpectedResult);
  $("#expectedResult").text(expectedResult);
}
addUp(); 
 input{
  width: 50px;
}
#expectedResult{
color: green;
}
#unexpectedResult{
color: red;
} 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="number1" value="0.2" onclick="addUp()" onkeyup="addUp()"/> +
<input id="number2" value="0.7" onclick="addUp()" onkeyup="addUp()"/> =
<p>Expected Result: <span id="expectedResult"></span></p>
<p>Unexpected Result: <span id="unexpectedResult"></span></p> 

Bu ┼čekilde kullanabilirsiniz:

 var x = 0.2 + 0.7;
floatify(x);  => Result: 0.9
 

W3SCHOOLS'un ├Ânerdi─či gibi ba┼čka bir ├ž├Âz├╝m de var; yukar─▒daki sorunu ├ž├Âzmek i├žin ├žo─čaltabilir ve b├Âlebilirsiniz:

 var x = (0.2 * 10 + 0.1 * 10) / 10;       // x will be 0.3
 

(0.2 + 0.1) * 10 / 10 Her ne kadar ayn─▒ g├Âr├╝nse de i┼če yaramayaca─č─▒n─▒ unutmay─▒n ! ─░lk ├ž├Âz├╝m├╝ tercih ediyorum ├ž├╝nk├╝ onu giri┼č ┼čamand─▒ras─▒n─▒ do─čru ├ž─▒k─▒┼č ┼čamand─▒ras─▒na d├Ân├╝┼čt├╝ren bir fonksiyon olarak uygulayabiliyorum.


17







Bu tuhaf say─▒lar, bilgisayarlar─▒n hesaplama amac─▒yla ikili (temel 2) say─▒ sistemini kullanmas─▒ nedeniyle g├Âr├╝n├╝rken, onluk (10 tabanl─▒).

─░kili veya ondal─▒k ya da her ikisinde de tam olarak temsil edilemeyen kesirli say─▒lar─▒n ├žo─ču vard─▒r. Sonu├ž - Yuvarlanm─▒┼č (ancak kesin) bir say─▒ sonu├žlar─▒.


16







Bu sorunun say─▒s─▒z kopyas─▒, kayan nokta yuvarlaman─▒n belirli say─▒lar ├╝zerindeki etkilerini soruyor. Uygulamada, sadece okumaktan ziyade, ilgi hesaplamalar─▒n─▒n kesin sonu├žlar─▒na bakarak nas─▒l ├žal─▒┼čt─▒─č─▒n─▒ hissetmek daha kolayd─▒r. B├Âyle bir d├Ân├╝┼čt├╝rme olarak - Baz─▒ dillerde bu yapman─▒n yollar─▒n─▒ sa─člamak float veya double kar┼č─▒ BigDecimal Java.

Bu dille ilgili bir soru oldu─čundan, Kayan Noktaya D├Ân├╝┼čt├╝r├╝c├╝ Ondal─▒─č─▒ gibi dille ilgili ara├žlara ihtiyac─▒ vard─▒r .

Sorudaki say─▒lara uygulamak, iki kat─▒na ├ž─▒karmak:

0.1, 0.1000000000000000055511151231257827021181583404541015625ÔÇÖe d├Ân├╝┼čt├╝r├╝l├╝r,

0.2, 0.200000000000000011102230246251565404236316680908203125ÔÇÖe ├ževirir,

0.3 0.299999999999999988897769753748434595763683319091796875ÔÇÖe d├Ân├╝┼čt├╝r├╝l├╝r ve

0,3000000000000000004 0,300000000000000000444089209850062616169452667236328125ÔÇÖe d├Ân├╝┼čt├╝r├╝l├╝r.

─░lk iki rakam─▒ manuel olarak veya Full Precision Calculator gibi bir ondal─▒k hesap makinesinde eklemek, ger├žek giri┼člerin tam toplam─▒n─▒n 0.3000000000000000000166533453693773481063544750213623046875 oldu─čunu g├Âsterir.

0.3 de─čerine yuvarlan─▒rsa, yuvarlama hatas─▒ 0.000000000000000000277555756156289135105907917022705078125 olur. 0.30000000000000004 de─čerine kadar yuvarlama i┼člemi ayr─▒ca 0.0000000000000000277955756156289135105907917022705078125 numaral─▒ yuvarlama hatas─▒n─▒ da verir. Yuvarlak-├žift ba─člant─▒ kesici uygulan─▒r.

Kayan nokta d├Ân├╝┼čt├╝r├╝c├╝s├╝ne d├Ânersek, 0.3000000000000000004 i├žin ham onalt─▒l─▒k 3fd3333333333334't├╝r, ki bu rakam d├╝z bir rakamla sona erer ve bu nedenle do─čru sonu├žtur.


15







Bundan kimsenin bahsetmedi─či g├Âz ├Ân├╝ne al─▒nd─▒─č─▒nda ...

Python ve Java gibi baz─▒ y├╝ksek seviyeli diller, ikili kayan nokta s─▒n─▒rlamalar─▒n─▒n ├╝stesinden gelmek i├žin ara├žlar ile birlikte gelir. ├ľrne─čin:

  • Python'un decimal mod├╝l├╝ ve Java'n─▒n BigDecimal s─▒n─▒f─▒ , dahili olarak ondal─▒k g├Âsterim ile say─▒lar─▒ g├Âsterir (ikili g├Âsterim yerine). Her ikisi de s─▒n─▒rl─▒ hassasiyete sahiptir, bu y├╝zden hala hata e─čilimlidirler, ancak ikili kayan nokta aritmeti─čindeki en yayg─▒n sorunlar─▒ ├ž├Âzerler.

    Onlarla para ile u─čra┼č─▒rken ├žok g├╝zel: on sent art─▒ yirmi sent her zaman tam otuz sent.

     >>> 0.1 + 0.2 == 0.3
    False
    >>> Decimal('0.1') + Decimal('0.2') == Decimal('0.3')
    True
     

    Python'un decimal mod├╝l├╝ IEEE standard─▒ 854-1987'ye dayanmaktad─▒r .

  • Python fractions mod├╝l├╝ ve Apache Common BigFraction s─▒n─▒f─▒ . Her ikisi de rasyonel say─▒lar─▒ (numerator, denominator) ├žiftler olarak temsil eder ve ondal─▒k kayan nokta aritmeti─činden daha do─čru sonu├žlar verebilir.

Bu ├ž├Âz├╝mlerin hi├žbiri m├╝kemmel de─čil (├Âzellikle performanslara bakarsak veya ├žok y├╝ksek bir hassasiyete ihtiya├ž duyarsak), ancak yine de ikili kayan nokta aritmeti─čiyle ilgili ├žok say─▒da sorunu ├ž├Âz├╝yorlar.


14







Sadece ekleyebilir miyim; insanlar her zaman bir bilgisayar bu sorunun varsayal─▒m, ama senin elinde (10 taban─▒) ile sayarsan─▒z, alamayan (1/3+1/3=2/3)=true sen 0.333 eklemek sonsuzluk yoksa ├Âylesine t─▒pk─▒ ile ... 0.333 kadar ... (1/10+2/10)!==3/10 taban─▒nda sorun 2'de, 0.333 + 0.333 = 0.666'ya k─▒salt─▒rs─▒n─▒z ve muhtemelen teknik olarak yanl─▒┼č olan 0.667'ye yuvarlars─▒n─▒z.

├ť├žl├╝ saymak ve ├╝├žte bir sorun olsa da sorun de─čil - belki her bir yandan 15 parma─č─▒n─▒zla yar─▒┼čmak, ondal─▒k matemati─činizin neden k─▒r─▒ld─▒─č─▒n─▒ sorabilir ...


14


2016-03-18





Dijital bir bilgisayarda uygulanabilecek kayan nokta matemati─či, mutlaka ├╝zerlerindeki ger├žek say─▒lar─▒n ve i┼člemlerin bir yakla┼č─▒k─▒n─▒ kullan─▒r. ( Standart s├╝r├╝m elli sayfadan fazla dok├╝mantasyona dayanmaktad─▒r ve hatal─▒ bir ┼čekilde ve daha fazla ayr─▒nt─▒land─▒r─▒lmas─▒ i├žin bir komitesi vard─▒r.)

Bu yakla┼č─▒m, her biri kesinlikten sapma ├Âzelli─čine ba─čl─▒ olarak ya g├Âz ard─▒ edilebilecek ya da dikkatle hesaplanabilecek farkl─▒ t├╝rde yakla┼č─▒mlar─▒n bir kar─▒┼č─▒m─▒d─▒r. Ayr─▒ca, ├žo─ču insan─▒n dikkatini ├žekmemi┼č gibi davran─▒rken hem ge├žmi┼čte y├╝r├╝d├╝─č├╝ hem donan─▒m hem de yaz─▒l─▒m d├╝zeyindeki istisnai durumlar─▒ i├žerir.

Sonsuz hassasiyete ihtiyac─▒n─▒z varsa (├Ârne─čin, k─▒sa bekleme s├╝relerinden biri yerine ¤Ç say─▒s─▒n─▒ kullan─▒n), bunun yerine sembolik bir matematik program─▒ yazmal─▒ veya kullanmal─▒s─▒n─▒z.

Ancak, bazen kayan noktal─▒ matemati─čin de─čer ve mant─▒k a├ž─▒s─▒ndan bulan─▒k oldu─ču ve hatalar─▒n h─▒zl─▒ bir ┼čekilde birikebilece─či ve bunun i├žin izin vermek i├žin gereksinimlerinizi ve testlerinizi yazabilece─činiz fikriniz varsa, o zaman kodunuz s─▒k s─▒k i├žinde ne olabilir? senin FPU.


10







Sadece e─člence i├žin, C99 Standard─▒ndaki tan─▒mlar─▒ izleyerek ┼čamand─▒ralar─▒n g├Âsterimi ile oynad─▒m ve a┼ča─č─▒daki kodu yazd─▒m.

Kod, 3 ayr─▒ grupta y├╝zd├╝rmelerin ikili g├Âsterimini yazd─▒r─▒r.

 SIGN EXPONENT FRACTION
 

ve bundan sonra, yeterince hassas bir ┼čekilde topland─▒─č─▒nda, ger├žekten donan─▒mda var olan de─čeri g├Âsterece─či bir toplam─▒ yazd─▒r─▒r.

B├Âylece, yazarken float x = 999... , derleyici, bu say─▒y─▒, i┼člev xx taraf─▒ndan bas─▒lan toplam─▒n yy verilen say─▒ya e┼čit olaca─č─▒ ┼čekilde , i┼člev taraf─▒ndan yazd─▒r─▒lan bir bit g├Âsteriminde d├Ân├╝┼čt├╝r├╝r .

Ger├žekte, bu toplam sadece bir yakla┼č─▒md─▒r. 999,999,999 say─▒s─▒ i├žin derleyici, y├╝zer y├╝z├╝n 1000.000.000 say─▒s─▒n─▒ temsili olarak ekleyecektir.

Koddan sonra, donan─▒mda ger├žekten var olan her iki sabit i├žin de (eksi PI ve 999999999) terimlerin toplam─▒n─▒ hesaplad─▒─č─▒m bir konsol oturumu ekliyorum.

 #include <stdio.h>
#include <limits.h>

void
xx(float *x)
{
    unsigned char i = sizeof(*x)*CHAR_BIT-1;
    do {
        switch (i) {
        case 31:
             printf("sign:");
             break;
        case 30:
             printf("exponent:");
             break;
        case 23:
             printf("fraction:");
             break;

        }
        char b=(*(unsigned long long*)x&((unsigned long long)1<<i))!=0;
        printf("%d ", b);
    } while (i--);
    printf("\n");
}

void
yy(float a)
{
    int sign=!(*(unsigned long long*)&a&((unsigned long long)1<<31));
    int fraction = ((1<<23)-1)&(*(int*)&a);
    int exponent = (255&((*(int*)&a)>>23))-127;

    printf(sign?"positive" " ( 1+":"negative" " ( 1+");
    unsigned int i = 1<<22;
    unsigned int j = 1;
    do {
        char b=(fraction&i)!=0;
        b&&(printf("1/(%d) %c", 1<<j, (fraction&(i-1))?'+':')' ), 0);
    } while (j++, i>>=1);

    printf("*2^%d", exponent);
    printf("\n");
}

void
main()
{
    float x=-3.14;
    float y=999999999;
    printf("%lu\n", sizeof(x));
    xx(&x);
    xx(&y);
    yy(x);
    yy(y);
}
 

Burada, ┼čamand─▒ran─▒n donan─▒mdaki ger├žek de─čerini hesaplad─▒─č─▒m bir konsol oturumu var. Kulland─▒─č─▒m bc ana programda taraf─▒ndan ├ž─▒k─▒┼č terimlerin toplam─▒n─▒ yazd─▒rmak i├žin. Biri bu toplam─▒ python'a repl veya benzer bir ┼čeye ekleyebilir .

 -- .../terra1/stub
@ qemacs f.c
-- .../terra1/stub
@ gcc f.c
-- .../terra1/stub
@ ./a.out
sign:1 exponent:1 0 0 0 0 0 0 fraction:0 1 0 0 1 0 0 0 1 1 1 1 0 1 0 1 1 1 0 0 0 0 1 1
sign:0 exponent:1 0 0 1 1 1 0 fraction:0 1 1 0 1 1 1 0 0 1 1 0 1 0 1 1 0 0 1 0 1 0 0 0
negative ( 1+1/(2) +1/(16) +1/(256) +1/(512) +1/(1024) +1/(2048) +1/(8192) +1/(32768) +1/(65536) +1/(131072) +1/(4194304) +1/(8388608) )*2^1
positive ( 1+1/(2) +1/(4) +1/(16) +1/(32) +1/(64) +1/(512) +1/(1024) +1/(4096) +1/(16384) +1/(32768) +1/(262144) +1/(1048576) )*2^29
-- .../terra1/stub
@ bc
scale=15
( 1+1/(2) +1/(4) +1/(16) +1/(32) +1/(64) +1/(512) +1/(1024) +1/(4096) +1/(16384) +1/(32768) +1/(262144) +1/(1048576) )*2^29
999999999.999999446351872
 

Bu kadar. Asl─▒nda 999999999ÔÇÖun de─čeri

 999999999.999999446351872
 

Ayr─▒ca bc -3.14'├╝n bozuldu─čunu da kontrol edebilirsiniz . Bir scale fakt├Âr ayarlamay─▒ unutma bc .

G├Âr├╝nt├╝lenen toplam, donan─▒m─▒n i├žindeki de─čerdir. Hesaplayarak elde etti─činiz de─čer, ayarlad─▒─č─▒n─▒z ├Âl├že─če ba─čl─▒d─▒r. scale Fakt├Âr├╝ 15 olarak belirledim . Matematiksel olarak, sonsuz hassasiyetle, 1.000.000.000 gibi g├Âr├╝n├╝yor.


9







Buna bakman─▒n ba┼čka bir yolu: Say─▒lar─▒ temsil etmek i├žin kullan─▒lan 64 bit. Sonu├ž olarak, 2 ** 64 = 18,446,744,073,709,551,616'dan daha fazla bir yol yoktur, farkl─▒ say─▒lar kesin olarak g├Âsterilebilir.

Bununla birlikte Math, zaten 0 ile 1 aras─▒nda sonsuz say─▒da ondal─▒k say─▒ oldu─čunu s├Âyl├╝yor. IEE 754, bu 64 bitin ├žok daha b├╝y├╝k bir say─▒ alan─▒ ve NaN ve +/- Infinity i├žin verimli bir ┼čekilde kullan─▒lmas─▒ i├žin bir kodlama tan─▒ml─▒yor, bu nedenle tam olarak g├Âsterilen say─▒lar aras─▒nda bo┼čluklar var. say─▒lar sadece yakla┼č─▒k.

Maalesef 0.3 bir bo┼člukta oturur.


5







Bu i┼č par├žac─▒─č─▒, ge├žerli kayan nokta uygulamalar─▒ hakk─▒nda genel bir tart─▒┼čmaya dalland─▒─č─▒ndan, sorunlar─▒n─▒ d├╝zeltmeye y├Ânelik projeler oldu─čunu eklerim.

├ľrne─čin, https://posithub.org/ ' a bak─▒n─▒z, ├Ârne─čin, daha az bit ile daha iyi do─čruluk sunmay─▒ vaat eden posit (ve ├Ânceki s├╝r├╝m) ad─▒nda bir say─▒ t├╝r├╝ g├Âsterir. Anlay─▒┼č─▒m do─čruysa, sorudaki problemleri de d├╝zeltir. Olduk├ža ilgin├ž bir proje, arkas─▒ndaki ki┼či bir matematik├ži olan Dr. John Gustafson . Her ┼čey, C / C ++, Python, Julia ve C # ( https://hastlayer.com/arithmetics ) ' de bir├žok ger├žek uygulamayla a├ž─▒k kaynak .


4







On numaral─▒ tabanda 8 do─črulukla ├žal─▒┼čt─▒─č─▒n─▒ d├╝┼č├╝n├╝n. Sen kontrol

 1/3 + 2 / 3 == 1
 

ve bunun d├Ând├╝─č├╝n├╝ ├Â─čren false . Niye ya? Eh, ger├žek say─▒lar olarak bizde

1/3 = 0.333 .... ve 2/3 = 0.666 ....

Sekiz ondal─▒k basama─ča d├╝┼čt├╝kten sonra

 0.33333333 + 0.66666666 = 0.99999999
 

Tabii ki 1.00000000 tam olarak farkl─▒ 0.00000001 .


Sabit say─▒da bit i├žeren ikili say─▒lar─▒n durumu tamamen benzerdir. Ger├žek say─▒lar olarak, biz var

1/10 = 0.0001100110011001100 ... (temel 2)

ve

1/5 = 0.0011001100110011001 ... (temel 2)

Bunlar─▒ yedi bit olarak kesersek, o zaman al─▒r─▒z.

 0.0001100 + 0.0011001 = 0.0100101
 

├ľte yandan,

3/10 = 0.01001100110011 ... (temel 2)

Bu, yedi bit olarak kesilir 0.0100110 ve bunlar tam olarak farkl─▒l─▒k g├Âsterir 0.0000001 .


Kesin durum biraz daha belirsizdir, ├ž├╝nk├╝ bu say─▒lar tipik olarak bilimsel g├Âsterimde saklan─▒r. Bu nedenle, ├Ârne─čin, ├╝s ve mantis i├žin ka├ž bit ay─▒rd─▒─č─▒m─▒za ba─čl─▒ olarak, 0.0001100 onu gibi bir ┼čey olarak saklayabilece─čimiz 1/10 depolamak yerine 1.10011 * 2^-4 . Bu, hesaplamalar─▒n─▒z i├žin ka├ž hassasiyet hanesini ald─▒─č─▒n─▒z─▒ etkiler.

Sonu├žta, bu yuvarlama hatalar─▒ nedeniyle, esasen asla kayan nokta say─▒lar─▒ == kullanmak istemezsiniz. Bunun yerine, farklar─▒n─▒n mutlak de─čerinin baz─▒ sabit k├╝├ž├╝k say─▒lardan daha k├╝├ž├╝k olup olmad─▒─č─▒n─▒ kontrol edebilirsiniz.


3







Python 3.5'ten bu yana math.isclose() yakla┼č─▒k e┼čitli─či test etmek i├žin i┼člev kullanabilirsiniz :

 >>> import math
>>> math.isclose(0.1 + 0.2, 0.3)
True
>>> 0.1 + 0.2 == 0.3
False
 

3







Asl─▒nda olduk├ža basit. 10 taban sistemine sahipseniz (bizimki gibi), sadece baz─▒n temel fakt├Âr├╝n├╝ kullanan kesirleri ifade edebilir. 10'luk ana fakt├Ârler 2 ve 5'tir. Yani 1/2, 1/4, 1/5, 1/8 ve 1/10 hepsi temiz bir ┼čekilde ifade edilebilir, ├ž├╝nk├╝ paydalar─▒n hepsi 10'un temel fakt├Ârlerini kullan─▒r. Bunun aksine, 1 / 3, 1/6 ve 1/7 hepsi tekrar eden de─čerlerdir, ├ž├╝nk├╝ paydalar─▒ 3 ya da 7'lik bir asal ├žarpan kullan─▒r. ─░kili (ya da baz 2) 'de, tek asal ├žarpan 2'dir. sadece ana fakt├Âr olarak 2 tane i├žerir. ─░kili olarak, 1/2, 1/4, 1/8, hepsi ondal─▒k olarak temiz bir ┼čekilde ifade edilir. 1/5 veya 1/10 ise ondal─▒k say─▒lar─▒ yineleyecekti. Yani 10 ve 0.2 (1/10 ve 1/5) taban 10 sistemindeki temiz ondal─▒k say─▒lar─▒ kullan─▒rken, taban 2 sistemindeki ondal─▒k say─▒lar─▒ bilgisayar ├žal─▒┼čt─▒r─▒r. Bilgisayar─▒n ├žal─▒┼čt─▒─č─▒ taban 2 sistemindeki ondal─▒k say─▒lar─▒ yineler. Bu, bilgisayar─▒n taban 2 (ikili) say─▒s─▒n─▒ daha insan taraf─▒ndan okunabilir bir taban 10 numaras─▒na d├Ân├╝┼čt├╝rd├╝─č├╝n├╝zde devam eder.

G├Ânderen https://0.30000000000000004.com/


3







Math.sum (javascript) .... operat├Âr de─či┼čtirme t├╝r├╝

 .1 + .0001 + -.1 --> 0.00010000000000000286
Math.sum(.1 , .0001, -.1) --> 0.0001
 

 Object.defineProperties(Math, {
    sign: {
        value: function (x) {
            return x ? x < 0 ? -1 : 1 : 0;
            }
        },
    precision: {
        value: function (value, precision, type) {
            var v = parseFloat(value), 
                p = Math.max(precision, 0) || 0, 
                t = type || 'round';
            return (Math[t](v * Math.pow(10, p)) / Math.pow(10, p)).toFixed(p);
        }
    },
    scientific_to_num: {  // this is from https://gist.github.com/jiggzson
        value: function (num) {
            //if the number is in scientific notation remove it
            if (/e/i.test(num)) {
                var zero = '0',
                        parts = String(num).toLowerCase().split('e'), //split into coeff and exponent
                        e = parts.pop(), //store the exponential part
                        l = Math.abs(e), //get the number of zeros
                        sign = e / l,
                        coeff_array = parts[0].split('.');
                if (sign === -1) {
                    num = zero + '.' + new Array(l).join(zero) + coeff_array.join('');
                } else {
                    var dec = coeff_array[1];
                    if (dec)
                        l = l - dec.length;
                    num = coeff_array.join('') + new Array(l + 1).join(zero);
                }
            }
            return num;
         }
     }
    get_precision: {
        value: function (number) {
            var arr = Math.scientific_to_num((number + "")).split(".");
            return arr[1] ? arr[1].length : 0;
        }
    },
    diff:{
        value: function(A,B){
            var prec = this.max(this.get_precision(A),this.get_precision(B));
            return +this.precision(A-B,prec);
        }
    },
    sum: {
        value: function () {
            var prec = 0, sum = 0;
            for (var i = 0; i < arguments.length; i++) {
                prec = this.max(prec, this.get_precision(arguments[i]));
                sum += +arguments[i]; // force float to convert strings to number
            }
            return Math.precision(sum, prec);
        }
    }
});
 

Fikir, Float hatalar─▒n─▒ ├Ânlemek i├žin operat├Ârleri yerine Math kullanmakt─▒r.

 Math.diff(0.2, 0.11) == 0.09 // true
0.2 - 0.11 == 0.09 // false
 

Ayr─▒ca Math.diff ve Math.sum'un kullan─▒lacak hassasiyeti otomatik olarak alg─▒lad─▒─č─▒n─▒ unutmay─▒n.

Math.sum, herhangi bir say─▒da ba─č─▒ms─▒z de─či┼čkeni kabul eder


2







Farkl─▒ bir soru, bunun bir kopyas─▒ olarak adland─▒r─▒ld─▒:

C ++ 'da neden cout << x bir hata ay─▒klay─▒c─▒n─▒n g├Âsterdi─či de─čerden farkl─▒ bir sonu├ž var x ?

S├Âz x konusu olan bir float de─či┼čkendir.

Bir ├Ârnek olurdu

 float x = 9.9F;
 

Hata ay─▒klay─▒c─▒ g├Âsterir 9.89999962 , cout i┼člemin ├ž─▒kt─▒s─▒ 9.9 .

Cevap, cout varsay─▒lan float de─čerinin 6 oldu─ču ┼čeklindedir, bu nedenle 6 ondal─▒k basama─ča yuvarlan─▒r.

Referans i├žin buraya bak─▒n─▒z


0


2018-05-30





Gibi Ondal─▒k fraksiyonlar 0.1 , 0.2 ve 0.3 tam olarak ikili temsil kayan nokta t├╝rleri kodlanmam─▒┼č. ─░├žin sadece yakla┼č─▒k toplam─▒ 0.1 ve 0.2 kullan─▒lan yakla┼č─▒m de─či┼čmesidir 0.3 , dolay─▒s─▒yla yalan 0.1 + 0.2 == 0.3 daha a├ž─▒k bir ┼čekilde buradan g├Âr├╝lebilece─či gibi:

 #include <stdio.h>

int main() {
    printf("0.1 + 0.2 == 0.3 is %s\n", 0.1 + 0.2 == 0.3 ? "true" : "false");
    printf("0.1 is %.23f\n", 0.1);
    printf("0.2 is %.23f\n", 0.2);
    printf("0.1 + 0.2 is %.23f\n", 0.1 + 0.2);
    printf("0.3 is %.23f\n", 0.3);
    printf("0.3 - (0.1 + 0.2) is %g\n", 0.3 - (0.1 + 0.2));
    return 0;
}
 

Çıktı:

 0.1 + 0.2 == 0.3 is false
0.1 is 0.10000000000000000555112
0.2 is 0.20000000000000001110223
0.1 + 0.2 is 0.30000000000000004440892
0.3 is 0.29999999999999998889777
0.3 - (0.1 + 0.2) is -5.55112e-17
 

Bu hesaplamalar─▒n daha g├╝venilir bir ┼čekilde de─čerlendirilmesi i├žin, kayan nokta de─čerleri i├žin ondal─▒k tabanl─▒ g├Âsterimler kullanman─▒z gerekir. C Standard─▒, bu tip de─čerleri varsay─▒lan olarak de─čil, Teknik Raporda a├ž─▒klanan bir uzant─▒ olarak belirtir . T├╝rleri _Decimal32 , _Decimal64 ve _Decimal128 mevcut olabilir sisteminizde (├Ârne─čin gcc ├╝zerine destekleri onlar─▒ se├žilen hedefler , ancak clang OS / X bunlar─▒ desteklemez).


0







Sadece bu ilgin├ž konuyu kayan noktalar─▒n etraf─▒nda g├Ârd├╝m:

A┼ča─č─▒daki sonu├žlar─▒ g├Âz ├Ân├╝nde bulundurun:

 error = (2**53+1) - int(float(2**53+1))
 
 >>> (2**53+1) - int(float(2**53+1))
1
 

Biz a├ž─▒k├ža bir k─▒r─▒lma noktas─▒n─▒ g├Ârebilirsiniz 2**53+1 t├╝m kadar para cezas─▒ i┼čleri - 2**53

 >>> (2**53) - int(float(2**53))
0
 


g├Âr├╝nt├╝ tan─▒m─▒n─▒ buraya girin

Bunun nedeni ├žift duyarl─▒kl─▒ ikili: IEEE 754 ├žift hassasiyetli ikili kayan nokta format─▒: binary64

├çift duyarl─▒kl─▒ kayan nokta format─▒ i├žin wikipedia sayfas─▒ndan :

├çift duyarl─▒kl─▒ ikili kayan nokta, performans─▒ ve bant geni┼čli─či maliyetine ra─čmen, tek duyarl─▒kl─▒ kayan noktaya g├Âre daha geni┼č bir yelpazeye sahip olmas─▒ nedeniyle PC'lerde yayg─▒n olarak kullan─▒lan bir formatt─▒r. Tek duyarl─▒kl─▒ kayan nokta bi├žiminde oldu─ču gibi, ayn─▒ boyutta bir tam say─▒ bi├žimiyle kar┼č─▒la┼čt─▒r─▒ld─▒─č─▒nda tam say─▒larda kesinli─či yoktur. Yayg─▒n olarak sadece ├žift olarak bilinir. IEEE 754 standard─▒, bir binary64'├╝ a┼ča─č─▒daki gibi belirtir:

  • ─░┼čaret biti: 1 bit
  • ├ťs: 11 bit
  • ├ľnemli hassasiyet: 53 bit (52 a├ž─▒k├ža depolanm─▒┼č)


g├Âr├╝nt├╝ tan─▒m─▒n─▒ buraya girin

Belirli bir ├Ânyarg─▒l─▒ ├╝s ve 52 bitlik bir kesir ile belirli bir 64 bit ├žift duyarl─▒kl─▒ verinin varsayd─▒─č─▒ ger├žek de─čer


g├Âr├╝nt├╝ tan─▒m─▒n─▒ buraya girin

veya


g├Âr├╝nt├╝ tan─▒m─▒n─▒ buraya girin

Bana i┼čaret etti─či i├žin @a_guest'e te┼čekk├╝rler.


0