2008-12-09 109 views
12

我正在考慮爲BigDecimal編寫兩個有限精度的替代方案,即DecimalInt和DecimalLong。這些將能夠處理int和real的邊界內的數字,並且具有任意數量的小數位,可以以可變和不可變形式創建。我的計劃是使DecimalInt支持+/- 999,999,999到+/- 0.999999999和DecimalLong相同,但最多可以有18位數。輕量級Java十進制類

這可以通過保持DecimalInt的十進制數字計數值爲0-9,並將DecimalLong的0-18保持爲存儲爲縮放的int或long的實際值。正常使用將用於小數小數點,例如貨幣和股票價格,通常是小數點後2-4位。基本要求是(a)精簡足跡(2個類別,加上OverflowException),和(b)全面支持所有基本操作以及所有有意義的數學運算。

谷歌搜索結果沒有返回任何明顯的命中 - 它們似乎都與任意小數有關。

我的問題是:這已經完成了嗎?這是否有隱藏的微妙之處,這就是爲什麼它尚未完成?有沒有人聽說過Java支持像DotNet這樣的十進制類型的傳言。

編輯:這與BigDecimal不同,因爲它應該是(a)更高效地處理整數數組,並且(b)它不會包裝BigInteger,因此它會更精簡記憶也(c)它會有一個可變的選項,所以它也會更快。總之 - 簡單用例的開銷較小,例如「我想存儲銀行餘額,而沒有BigDecimal的開銷和雙倍的不準確性」。

編輯:我打算做使用int或長的所有數學避免經典的問題:1586.60-708.75 = 877.8499999999999代替877.85

+0

「已經這個已經做了什麼?」你提出的類和BigDecimal有什麼不同? – 2008-12-09 20:12:05

+0

當你說「具有任意數量的小數位數」時,你的意思是說你有一個固定的小數位數,或者你希望能夠支持任意數量的小數位數? – DJClayworth 2008-12-10 14:25:01

+0

寫它可能會更快,而不必處理人們在這裏誤解你的問題。 – jmucchiello 2008-12-11 03:42:05

回答

0

如果你的重點是爲便攜式設備看Real。 Real允許將precision的號碼設置爲0到16.它專爲MIDP手機設計。

也感興趣,請看constructive reals庫。儘管這不是輕量級的。

參照下面的註釋,您是否不能使用Apache Commons Math Library來處理分數?有什麼理由不起作用嗎?

+0

真的看起來不錯,但是......它是GPL的,所以不能在商業上使用它,而且,它不是仍然是浮點數學,所以它會遇到小數不能用二進制表示的問題嗎? – 2008-12-09 21:47:10

+0

我沒有意識到您有許可證要求。 – WolfmanDragon 2008-12-11 01:53:27

-1

在我看來,如果你想要任意的精度,那麼你將需要一個未定義的位數來表示尾數。這意味着某種陣列分配策略對於尾數是必要的。你可以在這裏創建你自己的,但BigInteger相當有效地做到這一點,它的工作原理

你需要指定你需要表示的最小(非零)值是什麼。這將是10^- (2^n),其中n + 1是您分配給指數的位數。通過BigDecimal,這是10^- (2^31)。你可以使用任意大小的指數,但是這個範圍對任何人都是足夠的。

所以你需要的是一個無限的整數尾數給你任意的精度和一個固定大小的指數,這取決於你想要的最小可表示值是什麼。基本上這是BigDecimal;唯一的變化是你會使用一些較小的對象而不是BigDecimal使用的int。我懷疑空間節省是否值得。我認爲BigDecimal將會比你自己製作的任何解決方案更少地使用內存。

當然,您可以選擇最大數量的有效數字,您將需要;那麼你需要固定大小的存儲空間來存放尾數和指數,而這是一個很少的存儲空間。只需使用固定長度的尾數作爲尾數。

0

如果您正在尋找固定的小數位小數位來處理金錢,那麼通常通過保持整數(如果必要的話)長數字或百分之一分錢來完成。

如果你正在處理錢,那麼你將需要小心你如何處理舍入。如果你的計算將被審計,那麼這種事情是如何完成的。另外我假設你知道有些操作不能精確完成(除非是明顯的例子)。

12

我強烈懷疑爲什麼沒有這樣做的原因是BigDecimal和BigInteger的開銷不如您想象的那麼相關,並且避免它不值得花費精力和冒險以某種微妙的方式讓它出錯。

要使用您的示例:對於任何金融應用程序,保存幾十字節是一個無問題和有限精度的交易斷路器(股票價格在美國通常爲2-4位數字,但如果您想要在處理新興市場時,您會遇到通貨膨脹失控的貨幣,15位數字的總和會讓您購買一半面包)。

基本上,這聽起來像是另一種過早優化的情況。

1

大多數對舍入錯誤特別在意的人使用BigDecimal和BigInteger,它在大多數情況下表現良好。

但是,性能更爲重要的情況下,使用雙舍入可以完成這項工作。新手經常會忘記這一點,但如果沒有明智的回合,你就不能只取得雙重結果,並希望得到明智的答案。

在絕大多數情況下雙舍入是你所需要的。

System.out.printf("%.2f%n", 1586.60-708.75); 

打印

877.85