Bilgisayarlar neden ondalık sayıları ikinci bir tam sayı olarak saklamıyor?


24

Bilgisayarlar, paydayı 2 ^ x'e göre bir çözümden başka bir şey olduğu kesirli sayıları saklamakta zorlanıyor. Bunun nedeni, ondalık sayısından sonraki ilk hanenin 1/2, ikinci 1/4 (veya 1 / (2 ^ 1) ve 1 / (2 ^ 2)) vb.

Bilgisayar, sayının ondalık kısmını başka bir tam sayı olarak kaydetmişken neden bu kadar yuvarlama hatasıyla uğraşır (bu nedenle doğrudur?)

Aklıma gelen tek şey, tekrar eden ondalık sayılarla (10 no'lu adımda) başa çıkmak, ancak bunun için (şu anda sonsuzluğa sahip olduğumuz gibi) bir uç çözüm olabilirdi.


8
Float / double tiplerinin aksine ondalık tiplerin nasıl saklandığını araştırmalısınız.
Oded

9
Bunun nasıl daha doğru olduğunu bilmiyorum. Ondalıktan sonraki ilk hane 1/10, ikinci 1/100 vs.'dir. Yuvarlama problemlerini nasıl hala daha doğru yapabiliyorsunuz (1/3'ü nasıl temsil ediyorsunuz)? Tek fark, tam olarak temsil edilebilecek değerlerdir.
Martin York

17
Ondalık kayan nokta (ikiye neyi kastettiğinizdir, sadece daha garip bir gösterimde) ikili kayan noktadan daha yanlış değildir. Tek fark, hangi değerlerin temsil edilemeyeceğidir ve ondalık sisteme alışkın olduğumuz için ondalık sürümün hatalarını fark etmiyoruz. Ve hayır, hiçbiri rasyonel ve irrasyonel sayıları temsil edemez.

1
Günün sonunda, verim düşüyor. Bilgisayarlar ikilidir ve bu ikili gösterimle çalışacak devreler çok daha az karmaşıktır. Bunun önemi bugün biraz azalmış olabilir, ancak bunun çok önemli olduğu bir zamandı. Ayrıca, numaranızı bir bilgisayarda (sınırlı bir alanda) saklamayı seçtiğiniz herhangi bir ifade, temsil edebileceği sınırlı bir değer kümesine sahip olacak ve hepsi, bazı girdilerle birlikte yuvarlama hataları gösterecektir. Mantissa ve Exponent ile tipik kayan nokta formatı, iki tamsayı kullanarak çok daha geniş bir aralık sunar.
Mr.Mindor

1
Makalelerden bazılarını başvurulan aracılığıyla ederim okumayı tavsiye ederim Cevabıma soruya noktası yuvarlama hatalarını kayan neden olur nedir? Ben sadece başvurulan serideki son makalenin detayları ile güncellendi. Özellikle, Sabit Nokta Kayan Nokta Blues'unuzu Neden Tedavi Edemediğine bir bakın .
Mark Booth,

Yanıtlar:


35

Aslında bunu yapan sayı modları var.

İkili kodlu ondalık (BCD) aritmetik, bilgisayarın 10 tabanında çalışmasını sağlar. Buna nadiren rastlamanızın nedeni, boşa harcamasıdır: bir sayının her bir basamağı, en az dört bit alır; Bu boşlukta 16 değer. (Aynı zamanda daha yavaş olabilir, ancak iyi çalışan donanım hızlandırmalı BCD matematiğine sahip olmak mümkündür.). Bu, aslında, çoğu hesap makinesinin yaptığı şeydir, bu yüzden belli bir yuvarlama problemi sınıfı vardır, bu sayede öğlen yemeğinizi bir masaüstü bilgisayarda yiyecek bir Casio'ya asla varamazsınız.

Alabileceğiniz diğer rota ise rasyonel sayılar kullanmaktır - yani tamsayı olarak depolanan bir pay ve payda. Bu aslında hemen hemen tüm dillerde mevcuttur, kesindir ve her şeyi yerel ikili formatlarda saklamanıza izin verir. Sorun şu ki, günün sonunda kullanıcılar muhtemelen 463/13, hatta 35 ve 8/13 gibi kesirler görmek istemiyorlar. 35.615'i görmek istiyorlar ... ... ve oraya vardığın an, bütün tipik sorunlarla yüzleşiyorsun. Bu formatın daha fazla yer kapladığını ve kayan nokta aritmetiğinden çok daha yavaş olabileceğini ve varsayılan olarak bu formatı kullanmayan hiçbir bilgisayar bulamayacağınızı ekleyin .

Yani: bilgisayarlar ne istersen yapabilir, ama yavaş ve boşa harcıyor, bu yüzden sadece gerçekten yapmak zorunda kaldıklarında yapıyorlar. Zamanın geri kalanı, kayan noktanın hızı ve yer tasarrufu daha iyi bir dengedir.


BCD paragrafında dört bit (bayt değil) demek istemiyor musunuz ?

3
Diğer seçenek ise, bir sayının bir sayıyı temsil ettiği bir tamsayıyı ondalık kesir temsil ettiği sabit nokta aritmetiğidir.
mattnz

1
@ mattnz: Doğru — sabit noktalar, özel bir rasyonel durumdur.
Jon Purdy

Müthiş, hesap makinesinin yaptığını bilmiyordu.
SomeKittens

3
Üçüncü bir seçenek var. Ondalık üslü kayan nokta, C # ' decimalnın nasıl uygulandığı gibi: stackoverflow.com/a/5019178/174335 Ondalık basamakların hiçbiri gösterilemediğinden BCD değildir ve sabit nokta değildir.
Joren

38

Kesirli sayıları kaydetmenin sayısız yolu vardır ve her birinin avantaj ve dezavantajları vardır.

Kayan nokta , bugüne kadar en popüler biçimdir. Tamsayılara bir işaret, bir mantis ve imzalı bir üs-2 üssünü kodlayarak ve bunları bir demet bit olarak paketleyerek çalışır. Mesela, sen bir 32 bit mantis olabilir 0.5(olarak kodlanmış 0x88888888) ve bir 32 bitlik imzalı üs +3( 0x00000003için deşifre olurdu), 4.0(0.5 * 2 ^ 3). Kayan nokta sayıları hızlıdır, çünkü donanımda uygulanırlar ve kesin boyutları mutlak boyutta ölçeklenir, yani sayı ne kadar küçükse, mutlak hassasiyetiniz o kadar iyi olur, bu nedenle göreceli yuvarlama hatası mutlak boyutta sabit kalır. Şamandıralar, uzunluklar, ses basıncı seviyeleri, ışık seviyeleri vb. Gibi sürekli bir alandan örneklenen değerler için mükemmeldir ve bu nedenle, genel olarak ses ve görüntü işlemede, ayrıca istatistiksel analiz ve fizik simülasyonlarında kullanılırlar. En büyük dezavantajı, kesin olmadıkları, yani yuvarlama hatalarına yatkın oldukları ve tüm ondalık kesirleri doğru şekilde temsil edemedikleridir. Bütün ana programlama dilleri bir tür kayan noktaya sahiptir.

Sabit noktayeterince büyük tamsayılar kullanarak ve parçalarının bir kısmını kesirli kısım için dolaylı olarak ayırma yoluyla çalışır. Örneğin, 24.8 bitlik sabit nokta sayısı, tamsayı kısmı (işareti dahil) için 24 bit ve kısmi bölüm için 8 bit ayırır. Bu sayının 8 bit kadar sağa kaydırılması, bize tam sayı kısmını verir. Sabit nokta sayıları, donanım kayan nokta üniteleri nadir olduğunda ya da en azından tam sayılarına göre daha yavaştığında popülerdi. Sabit nokta sayıları doğruluk bakımından biraz daha kolay olsa da (sadece nedenini düşünmeleri daha kolay olduğu için), hemen hemen her alanda yüzmeye aşağı kalırlar - daha az hassasiyete, daha küçük bir aralığa sahiptirler ve çünkü Örtük kayma hesaplamalarını düzeltmek için işlem yapılması gerekir, bugün sabit nokta matematik genellikle kayan nokta matematikten daha yavaştır.

Ondalık türler kayan nokta veya sabit nokta sayıları gibi çalışır, ancak onlu bir sistem olduğunu varsayarlar; üstelik üsleri (örtük veya açık) 10'un gücünü (2'nin gücünü değil) kodlar. Ondalık bir sayı, örneğin, bir mantisini 23456ve bir üssünü kodlayabilir -2ve bu,234.56. Ondalık, çünkü aritmetik işlemciye CPU'ya bağlı değil, kayan noktalardan daha yavaş, ancak ondalık sayılar içeren ve bu sayının kesin olmasını gerektiren her şey için ideal, iyi tanımlanmış noktalarda yuvarlama - finansal hesaplamalar, çetele tahtaları, vb. Bazı programlama dilleri kendi içinde yerleşik olan ondalık tiplere sahiptir (örneğin, C #), bazıları ise bunları uygulamak için kütüphanelere ihtiyaç duyar. Ondalıklar, yinelenmeyen ondalık kesirleri doğru şekilde temsil edebiliyor olsa da, hassasiyetlerinin kayan nokta sayısından daha iyi olmadığını unutmayın; Ondalıkları seçmek, yalnızca bir ondalık sistemde tam olarak temsil edilebilecek sayıların tam temsilini elde edeceğiniz anlamına gelir (kayan noktaların tıpkı ikili kesirleri tam olarak temsil edebildiği gibi).

Rasyonel sayılar, tipik olarak bir tür bignum tamsayı türü (bilgisayarın bellek kısıtlamalarının izin verdiği kadar büyüyebilen sayısal bir tür) kullanarak bir payda veya bir payda saklar. Bu yalnızca veri doğru model numaraları gibi olabilir demet dışarı türüdür 1/3ya 3/17rationals, diğer veri türlerinin aksine, gibi şeyler için doğru sonuçlar üretecek - yanı üzerlerinde operasyonlarının olarak3 * 1/3. Matematik oldukça basittir, ancak etkili bir faktoring algoritması ile gelmesi oldukça zordur. Bazı programlama dilleri, içine yerleştirilmiş rasyonel tiplere sahiptir (örn. Common Lisp). Gerekçelerin dezavantajları, yavaş olmalarını (çoğu işlemin kesirleri azaltmayı ve bileşenlerini çarpanlara ayırmayı gerektirmesi) ve birçok ortak işlemin gerçekleştirilmesinin zor ya da imkansız olduğunu ve çoğu uygulamanın bu gerçekleştiğinde (örneğin, sin()rasyonel üzerinde).

BCD (İkili Kodlu Ondalık), her bir basamağı kodlamak için "nibbles" (4 bitlik gruplar) kullanır; Bir dişi 16 farklı değer tutabildiğinden, ancak ondalık sayılar sadece 10 gerektirdiğinden, diş başına 6 "kaçak" değer vardır. Ondalık gibi, BCD sayıları da kesindir, yani ondalık sayılar üzerinde yapılan hesaplamalar tıpkı kalem ve kâğıt kullanarak yaparsanız olduğu gibi çalışır. BCD için aritmetik kurallar biraz beceriksizdir, ancak bunun tersi, bunları dizelere dönüştürmenin, bazı gömülü sistemler gibi özellikle düşük kaynaklı ortamlar için ilginç olan diğer biçimlerden daha kolay olmasıdır.

Dizeler , evet, düz eski dizeler de kesirli sayıları temsil etmek için kullanılabilir. Teknik olarak, bu BCD'ye çok benzer, sadece açık bir ondalık nokta var ve ondalık basamak başına bir tam bayt kullanıyorsunuz. Bu nedenle, format israflıdır (256 olası değerden yalnızca 11'i kullanılır), ancak BCD'den ayrıştırılması ve oluşturulması daha kolaydır. Ek olarak, kullanılan tüm değerler "şüphesiz" olduğundan, zararsız ve platform açısından nötr, dize kodlu sayılar ağlar üzerinden sorunsuz şekilde dolaşabilir. Doğrudan dizgelerde aritmetik işlemlerin yapılması nadirdir, ancak mümkündür ve bunu yaptığınızda diğer ondalık biçimlerde (ondalık ve BCD) olduğu gibi tam olarak ondalık olurlar.


Şüphesiz 32 bit sabit nokta, 32 bit kayan noktadan daha fazla hassasiyete sahiptir, çünkü sabit nokta gösterimleri bir mantis içermez.
han,

4
@ han: Saklamak istediğiniz numaranın boyutuna bağlıdır. Şamandıralar (kabaca) size ne kadar büyük veya küçük olursa olsun aynı hassasiyeti verirken, sabit nokta yalnızca saklamak istediğiniz sayı aralığına tam olarak uyuyorsa size tam hassasiyet verecektir.
Leo

@han Mutlaka gerek yok, her ikisi de yine de 2 ^ 32 farklı değerleri temsil edebilir. Sunumdan bağımsız olarak taşınan bilgi miktarı aynıdır. Menzil ve hassasiyet el ele gider, bu nedenle sabit nokta aritmetiği belli aralıklarda daha doğru olabilir. İçinde çalışabileceğiniz sınırları biliyorsanız, rastgele kötü yuvarlama sorunlarından da kaçınırsınız.
zxcdw

@han: aynı hassasiyete sahipler (veya neredeyse). Aradaki fark, sabit nokta sayıları için kesinliğin (bir sayıdan ardılına ayrık bir adımın boyutunda olduğu gibi), tamsayılarda olduğu gibi sabittir; oysa yüzerde, kabaca doğrusal bir değerle mutlak değerde büyür - şamandıra 1.0 rakamı, 10.000.000.0 sayısından (kabaca milyon kat daha fazla) daha fazla hassasiyete sahiptir.
tdammers

6

Kayan nokta sayıları, değerlerin ne olabileceğini önceden bilmediğiniz zaman çok yararlı olan çok geniş bir değer aralığını temsil eder, ancak bu bir uzlaşmadır. 1/10 ^ 100'ü ikinci bir tamsayı ile göstermek işe yaramaz.

Bazı dillerin (ve bazı kütüphanelerin) başka özellikleri vardır. Lisp geleneksel olarak sonsuz hassas tam sayılara sahiptir. Cobol sabit nokta ondalık sayılarla hesaplamalara sahiptir.

Sayı temsilinizi, problem alanına uygun olarak seçmelisiniz.


1

Sabit nokta numaralarını tarif ediyor gibisiniz .

Bir sayının kesirli bölümünü ayrı bir yere kaydetmenin, iki katı uzunluğunda tek bir boşluk yaratmanın ve bütün ve kesirli parçanın iki ayrı yarıda depolanmasının tam olarak aynı olduğunu unutmayın. Başka bir deyişle, sayının bir tam sayı olarak depolanmasıyla aynıdır, ancak yalnızca sabit bir ondalık basamak sayılması varsayılır.

Normalde kayan noktalı sayılar, bilimsel gösterimde ikili bir varyasyon kullanılarak depolanır, çünkü genellikle önemli olan önemli basamaklardır. Yine de birçok başka yöntem var. Sabit nokta ondalık sayılar, örneğin, belirli bir sayıdaki ondalık basamağa kadar kesinliğin kritik olduğu, ancak gerekli ondalık basamağın hiçbir zaman değişmediği durumlarda, para birimlerinin depolanması için yaygın olarak kullanılır.


1

Buna BCD denirdi, gerçekten istersen hala kullanabileceğini düşünüyorum. Ancak buna gerçekten değmez:

  1. 64 bit kayan nokta ile çok nadiren bir yuvarlama hatasıyla karşılaşırsınız
  2. Aritmatik karmaşık ve verimsiz yapar
  3. Her 4 bitte 6 değer kaybediyor

BCD matematiği 8-bitlik mikroişlemcili sistemlerin ilklerinde çok kullanıldı; Gerçekten de, bir popüler mikroişlemcide (6502), BCD ile toplama ve çıkarma, ikili baytlar kadar bayt başına daha hızlıdır. Video oyunları, puan tutma için sık sık BCD matematiğini kullandı. 1.000.000 puanda toplanan puanlar için özel işlem yoktur. Bunun yerine 1 ila "99 99 99" eklemek, ihmal edilen bir taşıma ile "00 00 00" verir. BCD’de puan ekleme ek yükü, ikili bir değeri görüntülenebilir biçime dönüştürme maliyetine kıyasla küçüktür.
supercat

1

Kısa cevap, kayan noktaların bilimsel hesaplamalar için tasarlandığıdır. Birçok bilimsel hesaplamada kesinliğin ölçülmesine tam olarak uyan belirli sayıda önemli basamak içeren bir sayı saklayabilir.

Bu, büyük ölçüde donanımda desteklenme eğilimindedir, çünkü bilimsel hesaplamalar donanım desteğinden en fazla yararlananlar olma eğilimindedir. Örneğin, finansal hesaplamalar genellikle diğer formatlarla yapılır - ancak finansal yazılım, genellikle gerekli formatlar yalnızca yazılımda desteklense de, performansın çoğu finansal yazılım için mükemmel bir şekilde yeterli olacağı kadar, yeterince gerçek bir hesaplama yapmaz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.