|
|
#1 (permalink) |
|
Guest
Posts: n/a
|
Evening all,
I would quite like to represent some numbers in fixed point, and do arithmetic with them. These numbers will mostly not be more than a bilion, and will probably never be more than a hundred billion. Some of them, i will need to represent to eight decimal places. I'd like to be able to multiply two large numbers, but i suspect will not need to multiply three. 11 * 2 + 8 = 30 decimal digits; that's about 100 bits, so 128 bits would be big enough (about 5 decimal digits of headroom). Can anyone suggest an existing library for doing fixed-point arithmetic which would cover this? I have googled, but not found anything. There are a few fixed-precision libraries aimed at J2ME (i assume because old phones didn't have floating-point units?). There's something called jExigo, but it's 64-bit and the code doesn't look great. It's quite possible that there is no such library. But i thought it prudent to ask before writing one myself. Thanks, tom -- An artist is attracted to certain kinds of form without knowing why. You adopt a position intuitively; only later do you attempt to rationalize or even justify it. -- Fernando Botero |
|
|
|
#2 (permalink) |
|
Guest
Posts: n/a
|
If a decimal scale suits you, you could use:
http://docs.oracle.com/javase/7/docs...igDecimal.html Decimal scale means your numbers would be represented as: mantissa * 10 ^ -scale Bye Tom Anderson schrieb: > Evening all, > > I would quite like to represent some numbers in fixed point, and do > arithmetic with them. > > These numbers will mostly not be more than a bilion, and will probably > never be more than a hundred billion. Some of them, i will need to > represent to eight decimal places. I'd like to be able to multiply two > large numbers, but i suspect will not need to multiply three. 11 * 2 + 8 > = 30 decimal digits; that's about 100 bits, so 128 bits would be big > enough (about 5 decimal digits of headroom). > > Can anyone suggest an existing library for doing fixed-point arithmetic > which would cover this? > > I have googled, but not found anything. There are a few fixed-precision > libraries aimed at J2ME (i assume because old phones didn't have > floating-point units?). There's something called jExigo, but it's 64-bit > and the code doesn't look great. > > It's quite possible that there is no such library. But i thought it > prudent to ask before writing one myself. > > Thanks, > tom > |
|
|
|
#3 (permalink) |
|
Guest
Posts: n/a
|
On 22.02.2012 22:39, Tom Anderson wrote:
> Evening all, > > I would quite like to represent some numbers in fixed point, and do > arithmetic with them. Fixed point math is susceptible to precision issues which can be more severe than those of float and double: 0.01 * 0.2 -> 0.00 http://en.wikipedia.org/wiki/Fixed_p...s_and_overflow Out of curiosity: What do you want to do with that? > These numbers will mostly not be more than a bilion, and will probably > never be more than a hundred billion. Some of them, i will need to > represent to eight decimal places. I'd like to be able to multiply two > large numbers, but i suspect will not need to multiply three. 11 * 2 + 8 > = 30 decimal digits; that's about 100 bits, so 128 bits would be big > enough (about 5 decimal digits of headroom). > > Can anyone suggest an existing library for doing fixed-point arithmetic > which would cover this? > > I have googled, but not found anything. There are a few fixed-precision > libraries aimed at J2ME (i assume because old phones didn't have > floating-point units?). There's something called jExigo, but it's 64-bit > and the code doesn't look great. > > It's quite possible that there is no such library. But i thought it > prudent to ask before writing one myself. What about BigDecimal? http://docs.oracle.com/javase/6/docs...igDecimal.html You could either add the precision loss after operations or just apply it for output. package math; import java.math.BigDecimal; import java.math.RoundingMode; public class FixedPointMath { public static void main(String[] args) { BigDecimal bd1 = new BigDecimal("0.01"); BigDecimal bd2 = new BigDecimal("0.2"); BigDecimal bd3 = bd1.multiply(bd2); BigDecimal bd4 = bd3.setScale(2, RoundingMode.HALF_UP); System.out.println(bd1 + " * " + bd2 + " -> " + bd3 + " -> " + bd4); } } Alternatively you could use BigInteger and add the scaling logic yourself when cooking your fixed math lib. http://docs.oracle.com/javase/6/docs...igInteger.html Kind regards robert -- remember.guy do |as, often| as.you_can - without end http://blog.rubybestpractices.com/ |
|
|
|
#4 (permalink) |
|
Guest
Posts: n/a
|
On Wed, 22 Feb 2012 23:13:06 +0100, Robert Klemme
<shortcutter@googlemail.com> wrote: >On 22.02.2012 22:39, Tom Anderson wrote: >> Evening all, >> >> I would quite like to represent some numbers in fixed point, and do >> arithmetic with them. > >Fixed point math is susceptible to precision issues which can be more >severe than those of float and double: 0.01 * 0.2 -> 0.00 Only if the target precision does not have enough decimal places. I have been working with fixed-point arithmetic in JavaScript so that I can add dollar amounts exactly. Maybe OP has something similar in mind, though with the number of digits of precision that he wants before the decimal point, I hope it is not currency-related. [snip] Sincerely, Gene Wirchenko |
|
|
|
#5 (permalink) |
|
Guest
Posts: n/a
|
On Wed, 22 Feb 2012 14:59:12 -0800, Gene Wirchenko wrote:
> On Wed, 22 Feb 2012 23:13:06 +0100, Robert Klemme > <shortcutter@googlemail.com> wrote: > >>On 22.02.2012 22:39, Tom Anderson wrote: >>> Evening all, >>> >>> I would quite like to represent some numbers in fixed point, and do >>> arithmetic with them. >> >>Fixed point math is susceptible to precision issues which can be more >>severe than those of float and double: 0.01 * 0.2 -> 0.00 > > Only if the target precision does not have enough decimal places. > > I have been working with fixed-point arithmetic in JavaScript so > that I can add dollar amounts exactly. Maybe OP has something similar > in mind, though with the number of digits of precision that he wants > before the decimal point, I hope it is not currency-related. > Not necessarily. BigDecimal has few surprises, but then its not fixed decimal. The only fixed decimal arithmetic I've done in anger was in Cobol, which will merrily do the following (Identification and Environment divisions omitted for brevity). DATA DIVISION. WORKING-STORAGE. 01 FIXED-DECIMAL-FIELDS. 05 FD-VALUE PIC S9(6)v9(6) COMP SYNC. 05 FD-DIVISOR PIC S9(6)v9(6) COMP SYNC. 05 FD-RESULT PIC S9(6)v9(6) COMP SYNC. 05 FD-REMAINDER PIC S9(6)V9(6) COMP SYNC. 01 DISPLAY-LINE. 05 DL-VALUE PIC -(6)V.9(6). 05 FILLER PIC X() VALUE " / ". 05 DL-DIVISOR PIC -(6)V.9(6). 05 FILLER PIC X() VALUE " = ". 05 DL-RESULT PIC -(6)V.9(6). 05 FILLER PIC X() VALUE " REMAINDER ". 05 DL-REMAINDER PIC -(6)V.9(6). PROCEDURE DIVISION. MAIN SECTION. M-1. MOVE 0.8 TO FD-VALUE DL-VALUE. MOVE 2.0 TO FD-DIVISOR DL-DIVISOR. DIVIDE FD-VALUE BY FD-DIVISOR GIVING FD-RESULT REMAINDER FD-REMAINDER. MOVE FD-RESULT TO DL-RESULT. MOVE FD-REMAINDER TO DL-REMAINDER. DISPLAY DISPLAY-LINE. STOP RUN. This would display " 0.800000 / 2.000000 = 0.000000 REMAINDER 0.800000" because, of course, it is exactly equivalent to dividing 800000 by 2000000 and then adding decimal points in their correct fixed positions. Is that what you want or is BigDecimal doing the right thing for your problem space? Apologies for not showing a Cobol SSCE, but I don't have a COBOL compiler available to check it. -- martin@ | Martin Gregorie gregorie. | Es***, UK org | |
|
|
|
#6 (permalink) |
|
Guest
Posts: n/a
|
On Wed, 22 Feb 2012, Jan Burse wrote:
> If a decimal scale suits you, you could use: > > http://docs.oracle.com/javase/7/docs...igDecimal.html Decimal would be fine. BigDecimal might actually be okay too. I've actually misrepresented the context for this question slightly. My current place of work does a few calculations, and we currently use a fixed-point implementation of our own. However, it doesn't quite meet all our needs. My choice is really between extending it, and replacing it with something else. Being lazy, i would rather take advantage of someone else's hard work than do any myself. Now, we wrote this fixed-point implementation having previously used BigDecimal, because we had some serious performance problems with that. This was before my time, so i'm very hazy on the details. I had already dismissed BigDecimal out of hand on the basis of that, but it might actually be worth looking at again. I'd still be interested in any existing fixed-point libraries, as another option to consider. tom > Decimal scale means your numbers would be represented as: > > mantissa * 10 ^ -scale > > Bye > > Tom Anderson schrieb: > >> I would quite like to represent some numbers in fixed point, and do >> arithmetic with them. >> >> These numbers will mostly not be more than a bilion, and will probably >> never be more than a hundred billion. Some of them, i will need to >> represent to eight decimal places. I'd like to be able to multiply two >> large numbers, but i suspect will not need to multiply three. 11 * 2 + 8 >> = 30 decimal digits; that's about 100 bits, so 128 bits would be big >> enough (about 5 decimal digits of headroom). >> >> Can anyone suggest an existing library for doing fixed-point arithmetic >> which would cover this? >> >> I have googled, but not found anything. There are a few fixed-precision >> libraries aimed at J2ME (i assume because old phones didn't have >> floating-point units?). There's something called jExigo, but it's 64-bit >> and the code doesn't look great. >> >> It's quite possible that there is no such library. But i thought it >> prudent to ask before writing one myself. -- X is for ... EXECUTION! |
|
|
|
#7 (permalink) |
|
Guest
Posts: n/a
|
On Wed, 22 Feb 2012, Gene Wirchenko wrote:
> On Wed, 22 Feb 2012 23:13:06 +0100, Robert Klemme > <shortcutter@googlemail.com> wrote: > >> On 22.02.2012 22:39, Tom Anderson wrote: >> >>> I would quite like to represent some numbers in fixed point, and do >>> arithmetic with them. >> >> Fixed point math is susceptible to precision issues which can be more >> severe than those of float and double: 0.01 * 0.2 -> 0.00 > > Only if the target precision does not have enough decimal places. > > I have been working with fixed-point arithmetic in JavaScript so > that I can add dollar amounts exactly. Maybe OP has something similar > in mind, though with the number of digits of precision that he wants > before the decimal point, I hope it is not currency-related. It is currency-related. What's wrong with that? tom -- Lilith doesn't exist, but it's an interesting story. |
|
|
|
#8 (permalink) |
|
Guest
Posts: n/a
|
On Thu, 23 Feb 2012, Martin Gregorie wrote:
> The only fixed decimal arithmetic I've done in anger was in Cobol, which > will merrily do the following (Identification and Environment divisions > omitted for brevity). > > DATA DIVISION. > WORKING-STORAGE. > 01 FIXED-DECIMAL-FIELDS. > 05 FD-VALUE PIC S9(6)v9(6) COMP SYNC. > 05 FD-DIVISOR PIC S9(6)v9(6) COMP SYNC. > 05 FD-RESULT PIC S9(6)v9(6) COMP SYNC. > 05 FD-REMAINDER PIC S9(6)V9(6) COMP SYNC. > > 01 DISPLAY-LINE. > 05 DL-VALUE PIC -(6)V.9(6). > 05 FILLER PIC X() VALUE " / ". > 05 DL-DIVISOR PIC -(6)V.9(6). > 05 FILLER PIC X() VALUE " = ". > 05 DL-RESULT PIC -(6)V.9(6). > 05 FILLER PIC X() VALUE " REMAINDER ". > 05 DL-REMAINDER PIC -(6)V.9(6). > > PROCEDURE DIVISION. > MAIN SECTION. > M-1. > MOVE 0.8 TO FD-VALUE DL-VALUE. > MOVE 2.0 TO FD-DIVISOR DL-DIVISOR. > DIVIDE FD-VALUE BY FD-DIVISOR GIVING FD-RESULT REMAINDER FD-REMAINDER. > MOVE FD-RESULT TO DL-RESULT. > MOVE FD-REMAINDER TO DL-REMAINDER. > DISPLAY DISPLAY-LINE. > STOP RUN. > > > This would display > > " 0.800000 / 2.000000 = 0.000000 REMAINDER 0.800000" > > because, of course, it is exactly equivalent to dividing 800000 by > 2000000 and then adding decimal points in their correct fixed positions. .... right. Yes, this is indeed not great. But i don't think this is a correct implementation of fixed-point; what you actually have here is essentially integers which are being printed with a format with dots in, right? A fixed-point implementation of multiplication or division needs to do some scaling to get the right answers. > Is that what you want or is BigDecimal doing the right thing for your > problem space? I don't want what the COBOL does. I need to be able to divide by 2. tom -- Lilith doesn't exist, but it's an interesting story. |
|
|
|
#9 (permalink) |
|
Guest
Posts: n/a
|
On Thu, 23 Feb 2012 21:21:31 +0000, Tom Anderson
<twic@urchin.earth.li> wrote: >On Thu, 23 Feb 2012, Martin Gregorie wrote: > >> The only fixed decimal arithmetic I've done in anger was in Cobol, which >> will merrily do the following (Identification and Environment divisions >> omitted for brevity). [snipped COBOL code] >> This would display >> >> " 0.800000 / 2.000000 = 0.000000 REMAINDER 0.800000" >> >> because, of course, it is exactly equivalent to dividing 800000 by >> 2000000 and then adding decimal points in their correct fixed positions. > >... right. Yes, this is indeed not great. But i don't think this is a If you need exact decimal representation, it is good. >correct implementation of fixed-point; what you actually have here is >essentially integers which are being printed with a format with dots in, >right? A fixed-point implementation of multiplication or division needs to Well, yes, that is about what fixed-point is. Certainly, it is a common implementation of it. >do some scaling to get the right answers. COBOL handles the scaling automatically. >> Is that what you want or is BigDecimal doing the right thing for your >> problem space? > >I don't want what the COBOL does. I need to be able to divide by 2. You can do that with COBOL. Why do you think that you can not? Sincerely, Gene Wirchenko |
|
|
|
#10 (permalink) |
|
Guest
Posts: n/a
|
On 2/23/2012 1:15 PM, Tom Anderson wrote:
> ...we currently use a > fixed-point implementation of our own. However, it doesn't quite meet > all our needs. A big help for all of us would be to understand what needs, exactly, you have. What are the requirements for this class/package? Given that no one has offered anything besides BigDecimal, it might be moot as there doesn't seem to be a lot out there, but it might help narrow down any potential choices. > My choice is really between extending it, and replacing > it with something else. Being lazy, i would rather take advantage of > someone else's hard work than do any myself. Or you could contract out for it. Sounds like a fun little sideproject. We'd still need those requirements though. |
|