Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.misc > #2535 > unrolled thread
| Started by | Gordon Henderson <gordon+usenet@drogon.net> |
|---|---|
| First post | 2014-04-30 09:34 +0000 |
| Last post | 2014-05-14 17:40 +0100 |
| Articles | 20 on this page of 56 — 22 participants |
Back to article view | Back to comp.misc
BASIC is 50 Gordon Henderson <gordon+usenet@drogon.net> - 2014-04-30 09:34 +0000
Re: BASIC is 50 Ant <ant@zimage.comANT> - 2014-04-30 03:42 -0700
Re: BASIC is 50 Bob Eager <news0002@eager.cx> - 2014-04-30 10:46 +0000
Re: BASIC is 50 Gordon Henderson <gordon+usenet@drogon.net> - 2014-04-30 12:03 +0000
Re: BASIC is 50 Rich <rich@example.com> - 2014-04-30 11:12 +0000
Re: BASIC is 50 scott@alfter.diespammersdie.us (Scott Alfter) - 2014-04-30 15:56 +0000
Re: BASIC is 50 Rich <rich@example.com> - 2014-04-30 20:41 +0000
Re: BASIC is 50 Will Honea <whonea@whonea.net> - 2014-04-30 18:38 -0600
Re: BASIC is 50 Rich <rich@example.com> - 2014-05-01 02:38 +0000
Re: BASIC is 50 Will Honea <whonea@whonea.net> - 2014-04-30 22:50 -0600
Re: BASIC is 50 Rich <rich@example.com> - 2014-04-30 20:48 +0000
Re: BASIC is 50 Richard Kettlewell <rjk@greenend.org.uk> - 2014-05-02 09:27 +0100
Re: BASIC is 50 Tim Streater <timstreater@greenbee.net> - 2014-05-02 09:50 +0100
Re: BASIC is 50 "BartC" <bc@freeuk.com> - 2014-05-07 10:48 +0100
Re: BASIC is 50 Tim Streater <timstreater@greenbee.net> - 2014-05-07 10:57 +0100
Re: BASIC is 50 Huge <Huge@nowhere.much.invalid> - 2014-05-07 11:20 +0000
Re: BASIC is 50 "BartC" <bc@freeuk.com> - 2014-05-07 13:14 +0100
Re: BASIC is 50 Marko Rauhamaa <marko@pacujo.net> - 2014-05-07 16:05 +0300
Re: BASIC is 50 Paul Sture <nospam@sture.ch> - 2014-05-08 18:06 +0200
Re: BASIC is 50 Marko Rauhamaa <marko@pacujo.net> - 2014-05-08 20:17 +0300
Re: BASIC is 50 "James Harris" <james.harris.1@gmail.com> - 2014-05-07 16:08 +0100
Re: BASIC is 50 "BartC" <bc@freeuk.com> - 2014-05-07 18:38 +0100
Re: BASIC is 50 "James Harris" <james.harris.1@gmail.com> - 2014-05-07 19:09 +0100
Re: BASIC is 50 Huge <Huge@nowhere.much.invalid> - 2014-05-07 19:08 +0000
Re: BASIC is 50 greymausg@mail.com - 2014-05-08 10:15 +0000
Re: BASIC is 50 "BartC" <bc@freeuk.com> - 2014-05-08 11:38 +0100
Re: BASIC is 50 Paul Sture <nospam@sture.ch> - 2014-05-08 17:55 +0200
Re: BASIC is 50 Paul Sture <nospam@sture.ch> - 2014-05-08 17:44 +0200
Re: BASIC is 50 Rich <rich@example.com> - 2014-05-12 12:39 +0000
Re: BASIC is 50 Marko Rauhamaa <marko@pacujo.net> - 2014-05-12 16:06 +0300
Re: BASIC is 50 Ben Bacarisse <ben.usenet@bsb.me.uk> - 2014-05-12 22:48 +0100
Re: BASIC is 50 Rich <rich@example.com> - 2014-05-13 12:03 +0000
Re: BASIC is 50 "BartC" <bc@freeuk.com> - 2014-05-13 13:23 +0100
Re: BASIC is 50 Rich <rich@example.com> - 2014-05-13 16:22 +0000
Re: BASIC is 50 "BartC" <bc@freeuk.com> - 2014-05-13 19:42 +0100
Re: BASIC is 50 "BartC" <bc@freeuk.com> - 2014-05-13 19:49 +0100
Re: BASIC is 50 Rich <rich@example.com> - 2014-05-14 01:09 +0000
Re: BASIC is 50 "BartC" <bc@freeuk.com> - 2014-05-14 09:51 +0100
Re: BASIC is 50 bde@besplex.bde.org (Bruce Evans) - 2014-05-14 10:36 +0000
Re: BASIC is 50 "BartC" <bc@freeuk.com> - 2014-05-14 12:58 +0100
Re: BASIC is 50 bde@besplex.bde.org (Bruce Evans) - 2014-05-14 16:13 +0000
Re: BASIC is 50 "BartC" <bc@freeuk.com> - 2014-05-14 19:24 +0100
Re: BASIC is 50 Ben Bacarisse <ben.usenet@bsb.me.uk> - 2014-05-13 15:50 +0100
Re: BASIC is 50 Johny B Good <johnny-b-good@invalid.ntlworld.com> - 2014-05-01 02:50 +0100
Re: BASIC is 50 David Hume <David.Hume@example.com> - 2014-05-01 09:06 +0100
Re: BASIC is 50 Gordon Henderson <gordon+usenet@drogon.net> - 2014-05-01 09:56 +0000
Re: BASIC is 50 Rich <rich@example.com> - 2014-05-01 10:25 +0000
Re: BASIC is 50 Marko Rauhamaa <marko@pacujo.net> - 2014-05-01 16:43 +0300
Re: BASIC is 50 Gordon Henderson <gordon+usenet@drogon.net> - 2014-05-01 18:03 +0000
Re: BASIC is 50 Bob Eager <news0002@eager.cx> - 2014-05-01 21:35 +0000
Re: BASIC is 50 Rob <monst.oorzudo@ntlworld.com> - 2014-05-01 22:41 +0100
Re: BASIC is 50 David Hume <David.Hume@example.com> - 2014-05-02 09:26 +0100
Re: BASIC is 50 Hils <hils@saynotospam.net> - 2014-05-02 10:46 +0100
Re: BASIC is 50 Johny B Good <johnny-b-good@invalid.ntlworld.com> - 2014-05-02 23:11 +0100
Re: BASIC is 50 Anssi Saari <as@sci.fi> - 2014-04-30 17:51 +0300
Re: BASIC is 50 Peter Percival <peterxpercival@hotmail.com> - 2014-05-14 17:40 +0100
Page 2 of 3 — ← Prev page 1 [2] 3 Next page →
| From | "James Harris" <james.harris.1@gmail.com> |
|---|---|
| Date | 2014-05-07 16:08 +0100 |
| Message-ID | <lkdi9g$cpd$1@dont-email.me> |
| In reply to | #2673 |
"BartC" <bc@freeuk.com> wrote in message news:Xtpav.335997$5V5.276603@fx08.am4... > > > "Huge" <Huge@nowhere.much.invalid> wrote in message ... >> Pretty obvious you've never worked in finance or banking. > > I've written software that worked with currency. I used floating point. > But > not for banking. (In that particular application, it needed to work in two > linked currencies. The conversion rate between them was such that one or > the > other would generally always be a fraction of a cent wrong, rounded to the > nearest cent.) > > The only issue that might arise (and I can't remember it happening in my > code), is in rounding a value ending in 0.5 cents or very close, then you > have to decide to round up or down. The result might however have to match > the same calculation done elsewhere, where the rounding might be the other > way because their floating point result is different. (But there are ways > of > getting consistent, portable floating point results too.) > > (In any case, typical 64-bit floating point can represent amounts up to > nearly $100 trillion, expressed in whole cents.) The big problem with floating point is subtraction. All programmers using floats should be aware of it but I don't know if it is generally taught. Even with 64-bit floats if you have two intermediate results that are similar and you subtract one from the other the result may have lost lots of digits of precision. For example, if you have a precise but very small floating point number X such as 3.1415926539e-10 and the code does X = X + 1 X = X - 1 The code looks harmless but X will have lost a lot of its precision. It may now be only something like 3.1e-10. For financial applications decimal numbers or scaled integers are normally safer. James
[toc] | [prev] | [next] | [standalone]
| From | "BartC" <bc@freeuk.com> |
|---|---|
| Date | 2014-05-07 18:38 +0100 |
| Message-ID | <8duav.279147$Tp4.228677@fx11.am4> |
| In reply to | #2676 |
"James Harris" <james.harris.1@gmail.com> wrote in message news:lkdi9g$cpd$1@dont-email.me... > "BartC" <bc@freeuk.com> wrote in message > news:Xtpav.335997$5V5.276603@fx08.am4... >> (In any case, typical 64-bit floating point can represent amounts up to >> nearly $100 trillion, expressed in whole cents.) > > The big problem with floating point is subtraction. All programmers using > floats should be aware of it but I don't know if it is generally taught. > Even with 64-bit floats if you have two intermediate results that are > similar and you subtract one from the other the result may have lost lots > of digits of precision. > > For example, if you have a precise but very small floating point number X > such as 3.1415926539e-10 and the code does > > X = X + 1 > X = X - 1 > > The code looks harmless but X will have lost a lot of its precision. It > may now be only something like 3.1e-10. I think the precision will be lost as soon as you do X=X+1. Although you're right in that someone who expects X to be unchanged after those two assignments may not be aware of the problem. (It's like right-shifting an integer by N places followed by left-shifting by N places.) > For financial applications decimal numbers or scaled integers are normally > safer. But it's possible (depending on the number of decimals) they won't be able to represent 3.14159265359e-10 anyway. Maybe only 3.1e-10 ! Or 0. -- Bartc
[toc] | [prev] | [next] | [standalone]
| From | "James Harris" <james.harris.1@gmail.com> |
|---|---|
| Date | 2014-05-07 19:09 +0100 |
| Message-ID | <lkdss3$vi1$1@dont-email.me> |
| In reply to | #2677 |
"BartC" <bc@freeuk.com> wrote in message news:8duav.279147$Tp4.228677@fx11.am4... > > > "James Harris" <james.harris.1@gmail.com> wrote in message > news:lkdi9g$cpd$1@dont-email.me... >> "BartC" <bc@freeuk.com> wrote in message >> news:Xtpav.335997$5V5.276603@fx08.am4... > >>> (In any case, typical 64-bit floating point can represent amounts up to >>> nearly $100 trillion, expressed in whole cents.) >> >> The big problem with floating point is subtraction. All programmers using >> floats should be aware of it but I don't know if it is generally taught. >> Even with 64-bit floats if you have two intermediate results that are >> similar and you subtract one from the other the result may have lost lots >> of digits of precision. >> >> For example, if you have a precise but very small floating point number X >> such as 3.1415926539e-10 and the code does >> >> X = X + 1 >> X = X - 1 >> >> The code looks harmless but X will have lost a lot of its precision. It >> may now be only something like 3.1e-10. > > I think the precision will be lost as soon as you do X=X+1. Yes, although the precision of the floating point value of X is really unchanged at that point. Its precision is still the same number of digits that it was before. For the sake of choosing some numbers say it has 11 digits of precision both before and after the addition of 1. If 1 is not subsequently subtracted the value of X is still precise to 11 digits and fine as a highly precise floating point number. The lost information is now around the 20 digits mark which is almost always negligible. Still, on subtraction the result loses precision which is significant. > Although you're > right in that someone who expects X to be unchanged after those two > assignments may not be aware of the problem. (It's like right-shifting an > integer by N places followed by left-shifting by N places.) > >> For financial applications decimal numbers or scaled integers are >> normally >> safer. > > But it's possible (depending on the number of decimals) they won't be able > to represent 3.14159265359e-10 anyway. Maybe only 3.1e-10 ! Or 0. Yes. I was just trying to illustrate the problem with simple numbers. As you know, the issue would arise in the same way if the number of pennies in a person's account was 3 million and as a result of an intermediate calculation 10e18 was added and then a number close to 10e18 was subtracted. Mathematically the subtraction may be correct but the result in a computer would differ markedly. Don't get me wrong, I believe that floats can be used for finances as long as the programmer is extremely careful about intermediate values and does lots of boundary testing. But even then the code can become very hard to maintain safely. (I was prompted to reply because I saw the comment that 64-bit floats can represent up to $100 trillion. That may be true for static storage but they would be very difficult to do calculations on due to the danger of losing information.) James
[toc] | [prev] | [next] | [standalone]
| From | Huge <Huge@nowhere.much.invalid> |
|---|---|
| Date | 2014-05-07 19:08 +0000 |
| Message-ID | <bsvel8Fj03qU1@mid.individual.net> |
| In reply to | #2678 |
On 2014-05-07, James Harris <james.harris.1@gmail.com> wrote:
> (I was prompted to reply because I saw the comment that 64-bit floats can
> represent up to $100 trillion. That may be true for static storage but they
> would be very difficult to do calculations on due to the danger of losing
> information.)
Especially if you're trying to do the maths in the kinds of timescales required
for high frequency trading...
--
Today is Boomtime, the 54th day of Discord in the YOLD 3180
“Stupidity cannot be cured. Stupidity is the only universal capital crime;
the sentence is death. There is no appeal, and execution is carried out
automatically and without pity.”
[toc] | [prev] | [next] | [standalone]
| From | greymausg@mail.com |
|---|---|
| Date | 2014-05-08 10:15 +0000 |
| Message-ID | <slrnlmm4e9.ub.greymausg@gmaus.org> |
| In reply to | #2673 |
On 2014-05-07, BartC <bc@freeuk.com> wrote: > > > "Huge" <Huge@nowhere.much.invalid> wrote in message > news:bsuj7gFd631U1@mid.individual.net... >> On 2014-05-07, BartC <bc@freeuk.com> wrote: >>> "Rich" <rich@example.com> wrote in message >>> news:53616180$0$59815$c3e8da3$e074e489@news.astraweb.com... >>>> Scott Alfter <scott@alfter.diespammersdie.us> wrote: >>> >>>> 99.7099999999999999436561815002733055735006928443908691406250000000000000 >>>> >>>> This is why floating point can be dangerous, and why floating point >>>> should _NEVER_ ever be used to compute monetary values: >>> >>> Why not? Because the result might be off by a quadrillionth of a cent? >>> >>> Use rounding properly and it can be made to work (unless you're dealing >>> with >>> very large amounts such as the US debt then it's a bit trickier to avoid >>> errors starting to affect the cents). >> >> Pretty obvious you've never worked in finance or banking. > > I've written software that worked with currency. I used floating point. But > not for banking. (In that particular application, it needed to work in two > linked currencies. The conversion rate between them was such that one or the > other would generally always be a fraction of a cent wrong, rounded to the > nearest cent.) > > The only issue that might arise (and I can't remember it happening in my > code), is in rounding a value ending in 0.5 cents or very close, then you > have to decide to round up or down. The result might however have to match > the same calculation done elsewhere, where the rounding might be the other > way because their floating point result is different. (But there are ways of > getting consistent, portable floating point results too.) > > (In any case, typical 64-bit floating point can represent amounts up to > nearly $100 trillion, expressed in whole cents.) > [why floating point should not be used in finance] Those tiny amounts, added together, can be diverted, as in the salami scam. Python has decimal.Decimal for that sort of thing
[toc] | [prev] | [next] | [standalone]
| From | "BartC" <bc@freeuk.com> |
|---|---|
| Date | 2014-05-08 11:38 +0100 |
| Message-ID | <J8Jav.1$z21.0@fx12.am4> |
| In reply to | #2689 |
<greymausg@mail.com> wrote in message news:slrnlmm4e9.ub.greymausg@gmaus.org... > On 2014-05-07, BartC <bc@freeuk.com> wrote: >> (In any case, typical 64-bit floating point can represent amounts up to >> nearly $100 trillion, expressed in whole cents.) >> > > [why floating point should not be used in finance] > Those tiny amounts, added together, can be diverted, as in the salami > scam. Python has decimal.Decimal for that sort of thing That might be an *for* using floating point: If you calculate 2.7% interest on $1234.56, then floating point will give you $33.33312. You can see the 0.312 cents left over after rounding to $33.33 and can choose what to do with it. What happens to the 0.312 cents with 'decimal.Decimal'? -- Bartc
[toc] | [prev] | [next] | [standalone]
| From | Paul Sture <nospam@sture.ch> |
|---|---|
| Date | 2014-05-08 17:55 +0200 |
| Message-ID | <n0ms3b-3562.ln1@news.chingola.ch> |
| In reply to | #2673 |
On 2014-05-07, BartC <bc@freeuk.com> wrote: > > "Huge" <Huge@nowhere.much.invalid> wrote in message >> >> Pretty obvious you've never worked in finance or banking. > > I've written software that worked with currency. I used floating point. But > not for banking. (In that particular application, it needed to work in two > linked currencies. The conversion rate between them was such that one or the > other would generally always be a fraction of a cent wrong, rounded to the > nearest cent.) Currency is a different beast, because rates change with time. You need a separate currency gains/losses account to keep track of these differences (e.g. the differences between what you invoice and what you receive some time later). Round errors simply get absorbed in here. As an example of how large these sums can be, the first computer I worked with cost GBP 100,000 and was funded out of what my employer had made out of currency gains* the previous year on a turnover of GBP 12 million. * gains because the Pound Sterling took a hammering that year; invoices in foreign currencies realised more pounds by the time they were paid. -- Paul Sture The final step of #heartbleed recovery is to call your mother, and advise her to change her maiden name -- @gojomo
[toc] | [prev] | [next] | [standalone]
| From | Paul Sture <nospam@sture.ch> |
|---|---|
| Date | 2014-05-08 17:44 +0200 |
| Message-ID | <nbls3b-3562.ln1@news.chingola.ch> |
| In reply to | #2670 |
On 2014-05-07, BartC <bc@freeuk.com> wrote: > "Rich" <rich@example.com> wrote in message > news:53616180$0$59815$c3e8da3$e074e489@news.astraweb.com... >> Scott Alfter <scott@alfter.diespammersdie.us> wrote: > >> 99.7099999999999999436561815002733055735006928443908691406250000000000000 >> >> This is why floating point can be dangerous, and why floating point >> should _NEVER_ ever be used to compute monetary values: > > Why not? Because the result might be off by a quadrillionth of a cent? That quadrillionth of a cent will sooner or later make the difference between rounding up and rounding down, and then your books don't add up. > Use rounding properly and it can be made to work (unless you're dealing with > very large amounts such as the US debt then it's a bit trickier to avoid > errors starting to affect the cents). You can see the effects of floating point inaccuracies within a one page invoice; let that loose on a full set of company accounts and the auditors aren't going to sign them. > You can also work with whole cents or pence for fewer problems, but at some > point (for tax calculations, compound interest etc) you will need to do more > complex arithmetic. In all my accounting and payroll work we used pence and rounding was done by "half adjusting". Even doing that you have to be careful. Our shiny new invoicing system back in 1978 was making a mistake with the VAT (sales tax) because it itemised the tax on a line item basis (so the customer could see the net, tax and gross amounts for each item) but calculated the VAT due on the invoice total rather than adding up the VAT on the line items. Easy to fix once we realised what was going on, but there are no doubt novices out there still making that mistake. FWIW the pocket calculator I had in 1987 wasn't up to the task of doing a month's accounts. I was simply checking that the row totals equalled the column totals for a set of figures and the damn thing couldn't get the same answer for both. I went out the following day and purchased a proper accounting desk calculator which could get those figures right. -- Paul Sture The final step of #heartbleed recovery is to call your mother, and advise her to change her maiden name -- @gojomo
[toc] | [prev] | [next] | [standalone]
| From | Rich <rich@example.com> |
|---|---|
| Date | 2014-05-12 12:39 +0000 |
| Message-ID | <5370c119$0$59769$c3e8da3$e074e489@news.astraweb.com> |
| In reply to | #2670 |
BartC <bc@freeuk.com> wrote:
> "Rich" <rich@example.com> wrote in message
> news:53616180$0$59815$c3e8da3$e074e489@news.astraweb.com...
> > Scott Alfter <scott@alfter.diespammersdie.us> wrote:
> > 99.7099999999999999436561815002733055735006928443908691406250000000000000
> >
> > This is why floating point can be dangerous, and why floating point
> > should _NEVER_ ever be used to compute monetary values:
> Why not? Because the result might be off by a quadrillionth of a cent?
> Use rounding properly and it can be made to work (unless you're dealing with
> very large amounts such as the US debt then it's a bit trickier to avoid
> errors starting to affect the cents).
> You can also work with whole cents or pence for fewer problems, but at some
> point (for tax calculations, compound interest etc) you will need to do more
> complex arithmetic.
An excellent writeup of "why not" is given here:
http://speleotrove.com/decimal/decifaq1.html#inexact
Reading the whole is better, but here is a small quote:
"For example, using the Java or C double datatype, 0.1 × 8 (a binary
multiple) gives the result
0.8000000000000000444089209850062616169452667236328125 but 0.1
added to itself 8 times gives the different answer
0.79999999999999993338661852249060757458209991455078125. The two
results would not compare equal, and further, if these values are
multiplied by ten and rounded to the nearest integer below (the
"floor" function), the result will be 8 in one case and 7 in the
other."
[toc] | [prev] | [next] | [standalone]
| From | Marko Rauhamaa <marko@pacujo.net> |
|---|---|
| Date | 2014-05-12 16:06 +0300 |
| Message-ID | <877g5rdu3t.fsf@elektro.pacujo.net> |
| In reply to | #2755 |
Rich <rich@example.com>: > Reading the whole is better, but here is a small quote: > > "For example, using the Java or C double datatype, 0.1 × 8 (a > binary multiple) gives the result > 0.8000000000000000444089209850062616169452667236328125 but 0.1 > added to itself 8 times gives the different answer > 0.79999999999999993338661852249060757458209991455078125. The two > results would not compare equal, and further, if these values are > multiplied by ten and rounded to the nearest integer below (the > "floor" function), the result will be 8 in one case and 7 in the > other." Why would you round like that? The age-old technique is floor(x + 0.5). Marko
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2014-05-12 22:48 +0100 |
| Message-ID | <0.749162ecb023be910298.20140512224801BST.878uq6u0ry.fsf@bsb.me.uk> |
| In reply to | #2755 |
Rich <rich@example.com> writes: > BartC <bc@freeuk.com> wrote: >> "Rich" <rich@example.com> wrote in message >> news:53616180$0$59815$c3e8da3$e074e489@news.astraweb.com... >> > Scott Alfter <scott@alfter.diespammersdie.us> wrote: > >> > 99.7099999999999999436561815002733055735006928443908691406250000000000000 >> > >> > This is why floating point can be dangerous, and why floating point >> > should _NEVER_ ever be used to compute monetary values: > >> Why not? Because the result might be off by a quadrillionth of a cent? > >> Use rounding properly and it can be made to work (unless you're dealing with >> very large amounts such as the US debt then it's a bit trickier to avoid >> errors starting to affect the cents). > >> You can also work with whole cents or pence for fewer problems, but at some >> point (for tax calculations, compound interest etc) you will need to do more >> complex arithmetic. > > An excellent writeup of "why not" is given here: > > http://speleotrove.com/decimal/decifaq1.html#inexact I am sure this is an excellent write-up of the perils of doing financial calculations using binary floating-point arithmetic, but it can't possible answer the "why not?" as applied to the original question. First, because the original claim was about using floating point, not about using binary floating point and, second, because it was far too broad. It's a common Usenet problem: someone makes a slightly overly broad claim, and when questioned, the defence is of a more limited claim, and then some knob-head like me comes along and points that out. Are representational and arithmetic errors the reason why you should _NEVER_ (note: CAPS *and* _underlined_) use floating point for monetary calculations? No, I use floating point in financial spreadsheets all the time for things like my home budget. What's more, I know a fund manager (managing millions) who does the same. They want to know data about company performance where the cents are of no importance at all. > Reading the whole is better, but here is a small quote: > > "For example, using the Java or C double datatype, 0.1 × 8 (a binary > multiple) gives the result > 0.8000000000000000444089209850062616169452667236328125 but 0.1 > added to itself 8 times gives the different answer > 0.79999999999999993338661852249060757458209991455078125. The two > results would not compare equal, and further, if these values are > multiplied by ten and rounded to the nearest integer below (the > "floor" function), the result will be 8 in one case and 7 in the > other." That calculation comes out fine using decimal floating point. I also detect a whiff of polemic here. Describing floor as "rounding to the nearest integer below" suggests some similarity with rounding to the nearest integer which is reasonable, even in some financial contexts, but while floor has mathematical uses I struggle to think of a reasonable financial one. (And there a technical error: C does not specify much about the floating point implementation. It might even be decimal floating-point, in which case the result would be exactly as expected.) -- Ben.
[toc] | [prev] | [next] | [standalone]
| From | Rich <rich@example.com> |
|---|---|
| Date | 2014-05-13 12:03 +0000 |
| Message-ID | <537209fc$0$17199$c3e8da3$dd9697d2@news.astraweb.com> |
| In reply to | #2768 |
Ben Bacarisse <ben.usenet@bsb.me.uk> wrote: > I am sure this is an excellent write-up of the perils of doing > financial calculations using binary floating-point arithmetic, but it > can't possible answer the "why not?" as applied to the original > question. First, because the original claim was about using floating > point, not about using binary floating point and, second, because it > was far too broad. It's a common Usenet problem: someone makes a > slightly overly broad claim, and when questioned, the defence is of a > more limited claim, and then some knob-head like me comes along and > points that out. Fair enough. You are quite correct. My original statement was overly broad. I meant to say "binary floating point" but wrote "floating point". The ubiquity of "binary floating point" has resulted in my refering to the format as simply "floating point" more often than not, even though such reference is incorrect.
[toc] | [prev] | [next] | [standalone]
| From | "BartC" <bc@freeuk.com> |
|---|---|
| Date | 2014-05-13 13:23 +0100 |
| Message-ID | <Y8ocv.64639$8%2.40203@fx06.am4> |
| In reply to | #2772 |
"Rich" <rich@example.com> wrote in message news:537209fc$0$17199$c3e8da3$dd9697d2@news.astraweb.com... > Ben Bacarisse <ben.usenet@bsb.me.uk> wrote: >> I am sure this is an excellent write-up of the perils of doing >> financial calculations using binary floating-point arithmetic, but it >> can't possible answer the "why not?" as applied to the original >> question. First, because the original claim was about using floating >> point, not about using binary floating point and, second, because it >> was far too broad. It's a common Usenet problem: someone makes a >> slightly overly broad claim, and when questioned, the defence is of a >> more limited claim, and then some knob-head like me comes along and >> points that out. > > Fair enough. You are quite correct. My original statement was overly > broad. I meant to say "binary floating point" but wrote "floating > point". The ubiquity of "binary floating point" has resulted in my > refering to the format as simply "floating point" more often than not, > even though such reference is incorrect. I meant binary floating point too. I haven't really thought about a decimal version (but sounds like an interesting project to complement my decimal integer library). > An excellent writeup of "why not" is given here: > > http://speleotrove.com/decimal/decifaq1.html#inexact Most of that article is about not understanding how to use (binary) floating point effectively. Given enough precision, I believe that binary floating point can emulate what can be done in decimal arithmetic. -- Bartc
[toc] | [prev] | [next] | [standalone]
| From | Rich <rich@example.com> |
|---|---|
| Date | 2014-05-13 16:22 +0000 |
| Message-ID | <537246b1$0$59749$c3e8da3$e074e489@news.astraweb.com> |
| In reply to | #2773 |
BartC <bc@freeuk.com> wrote: > "Rich" <rich@example.com> wrote in message > news:537209fc$0$17199$c3e8da3$dd9697d2@news.astraweb.com... > > Ben Bacarisse <ben.usenet@bsb.me.uk> wrote: > >> I am sure this is an excellent write-up of the perils of doing > >> financial calculations using binary floating-point arithmetic, but it > >> can't possible answer the "why not?" as applied to the original > >> question. First, because the original claim was about using floating > >> point, not about using binary floating point and, second, because it > >> was far too broad. It's a common Usenet problem: someone makes a > >> slightly overly broad claim, and when questioned, the defence is of a > >> more limited claim, and then some knob-head like me comes along and > >> points that out. > > > > Fair enough. You are quite correct. My original statement was > > overly broad. I meant to say "binary floating point" but wrote > > "floating point". The ubiquity of "binary floating point" has > > resulted in my refering to the format as simply "floating point" > > more often than not, even though such reference is incorrect. > I meant binary floating point too. I haven't really thought about a > decimal version (but sounds like an interesting project to complement > my decimal integer library). It (binary) floating point is so ubiquitous that I don't think we are alone in conflating "floating point" with "binary floating point". > > An excellent writeup of "why not" is given here: > > > > http://speleotrove.com/decimal/decifaq1.html#inexact > Most of that article is about not understanding how to use (binary) > floating point effectively. > Given enough precision, I believe that binary floating point can > emulate what can be done in decimal arithmetic. Actually, no. 0.1 in decimal is an infinite repeating sequence in binary floating point. So it is impossible to have enough precision to exactly represent 0.1 (decimal) in binary floating point. I.e., 0.1 is the same as 1/3 in decimal. The decimal representation of 1/3 is an infinite repeating sequence. The problem comes about because humans with math backgrounds understand where the inexactness exists for decimal (1/3, 2/3, etc.). With binary representations there are even more inexact items and so the opportunity for many more surprising results occurs. From the page above: "Similarly, the Java or C expression (0.1+0.2==0.3) evaluates to false."
[toc] | [prev] | [next] | [standalone]
| From | "BartC" <bc@freeuk.com> |
|---|---|
| Date | 2014-05-13 19:42 +0100 |
| Message-ID | <JJtcv.95786$Sp6.12404@fx15.am4> |
| In reply to | #2775 |
"Rich" <rich@example.com> wrote in message
news:537246b1$0$59749$c3e8da3$e074e489@news.astraweb.com...
> BartC <bc@freeuk.com> wrote:
>> Given enough precision, I believe that binary floating point can
>> emulate what can be done in decimal arithmetic.
>
> Actually, no.
>
> 0.1 in decimal is an infinite repeating sequence in binary floating
> point. So it is impossible to have enough precision to exactly
> represent 0.1 (decimal) in binary floating point.
> "Similarly, the Java or C expression (0.1+0.2==0.3) evaluates to
> false."
No, it's nothing to do with not being able to represent 0.1 exactly. You
*know* it's an approximation, but can work with that provided the precision
is greater than the number of decimal digits you're trying to emulate.
The following is an example of how it can be done (see main()). Actually,
you can replace the definition of 'myfloat' with just 'float' instead of
'double', and it will still work (but up to a smaller magnitude). This code
emulates some decimal arithmetic with two decimal places. (Note that the
normal 0.1+0.2==0.3 can give True with some compilers.)
/* Floating emulation of fixed point decimal arithmetic */
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define decimals 2
#define rounding 0.005
#define factor 100.0
//#define myfloat float
#define myfloat double
myfloat round_dec(myfloat x){
if (x>0.0)
return floor((x+rounding)*factor)/factor;
else
if (x>-rounding) return 0.0;
return ceil((x-rounding)*factor)/factor;
}
myfloat add_dec(myfloat x, myfloat y){
return round_dec(x+y);
}
myfloat sub_dec(myfloat x, myfloat y){
return round_dec(x-y);
}
myfloat mul_dec(myfloat x, myfloat y){
return round_dec(x*y);
}
int equal_dec(myfloat x, myfloat y){
return fabs(x-y)<rounding;
}
char* str_dec(myfloat x){
static char str[500];
sprintf(str,"%.2f (%.28f)",round_dec(x),x);
return str;
}
int main(void) {
myfloat x,y,z;
int i;
puts("Normal floating point:");
printf("0.1 = %.28f\n",0.1);
printf("0.2 = %.28f\n",0.2);
printf("0.1+0.3 = %.28f\n",0.3);
printf("0.1+0.2 == 0.3 = %s\n", (0.1+0.2==0.3)?"True":"False");
x=0.1;
y=x*8.0;
z=0.1;
for (i=1; i<=7; ++i)
z=z+0.1;
printf("0.1*8 = %.28f\n",y);
printf("0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1 = %.28f\n",z);
printf("Difference: = %.28f\n",y-z);
puts("\nDecimal emulation using same floating point type:");
printf("0.1 = %s\n",str_dec(0.1));
printf("0.2 = %s\n",str_dec(0.2));
printf("0.1+0.3 = %s\n",str_dec(add_dec(0.1,0.2)));
printf("0.1+0.2 == 0.3 = %s\n",
equal_dec(add_dec(0.1,0.2),0.3)?"True":"False");
x=0.1;
y=mul_dec(x,8.0);
z=0.1;
for (i=1; i<=7; ++i)
z=add_dec(z,0.1);
printf("0.1*8 = %s\n",str_dec(y));
printf("0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1 = %s\n",str_dec(z));
printf("Difference: = %s\n",str_dec(y-z));
}
--
Bartc
[toc] | [prev] | [next] | [standalone]
| From | "BartC" <bc@freeuk.com> |
|---|---|
| Date | 2014-05-13 19:49 +0100 |
| Message-ID | <XOtcv.72133$Ch2.21998@fx13.am4> |
| In reply to | #2780 |
"BartC" <bc@freeuk.com> wrote in message news:JJtcv.95786$Sp6.12404@fx15.am4... > The following is an example of how it can be done (see main()). Actually, A couple of the printfs were messed up. A fixed, downloadable version is here: http://pastebin.com/0TRdD52q -- Bartc
[toc] | [prev] | [next] | [standalone]
| From | Rich <rich@example.com> |
|---|---|
| Date | 2014-05-14 01:09 +0000 |
| Message-ID | <5372c23d$0$17205$c3e8da3$dd9697d2@news.astraweb.com> |
| In reply to | #2782 |
BartC <bc@freeuk.com> wrote: > "BartC" <bc@freeuk.com> wrote in message > news:JJtcv.95786$Sp6.12404@fx15.am4... > > The following is an example of how it can be done (see main()). Actually, > A couple of the printfs were messed up. > A fixed, downloadable version is here: > http://pastebin.com/0TRdD52q Nice. An educational read. Thanks for that one.
[toc] | [prev] | [next] | [standalone]
| From | "BartC" <bc@freeuk.com> |
|---|---|
| Date | 2014-05-14 09:51 +0100 |
| Message-ID | <I9Gcv.91670$vt2.2348@fx36.am4> |
| In reply to | #2790 |
"Rich" <rich@example.com> wrote in message news:5372c23d$0$17205$c3e8da3$dd9697d2@news.astraweb.com... > BartC <bc@freeuk.com> wrote: >> "BartC" <bc@freeuk.com> wrote in message >> news:JJtcv.95786$Sp6.12404@fx15.am4... > >> > The following is an example of how it can be done (see main()). >> > Actually, > >> A couple of the printfs were messed up. > >> A fixed, downloadable version is here: > >> http://pastebin.com/0TRdD52q > > Nice. An educational read. Thanks for that one. Odd how slight changes creep in between testing and posting! (I think because one compiler out of seven had trouble with it and I was trying to find out why.) I couldn't edit the 'guest' version above. But if someone wants to run the code, it's best to change the "(%f)" in str_dec() to "(%.28f)", or use this version: http://pastebin.com/uwpzHLH6 which shows the decimal results accompanied by a more precise internal representation, to highlight that the underlying values still have the inaccuracies, yet do not affect the ability to emulate decimal arithmetic. There is still the problem that a result ending in more or less exactly x.xx5 (using 2 decimal places) can be rounded either up or down depending on slight differences in the floating point representation between machines. However that would be an issue with true decimal arithmetic too (what is half of 0.99 expressed to 2 decimals places?). But I think that whatever behaviour is stipulated for such matters, could also be emulated. -- Bartc
[toc] | [prev] | [next] | [standalone]
| From | bde@besplex.bde.org (Bruce Evans) |
|---|---|
| Date | 2014-05-14 10:36 +0000 |
| Message-ID | <lkvgvv$19v$1@dont-email.me> |
| In reply to | #2780 |
In article <JJtcv.95786$Sp6.12404@fx15.am4>, BartC <bc@freeuk.com> wrote:
>"Rich" <rich@example.com> wrote in message
>news:537246b1$0$59749$c3e8da3$e074e489@news.astraweb.com...
>> BartC <bc@freeuk.com> wrote:
>
>>> Given enough precision, I believe that binary floating point can
>>> emulate what can be done in decimal arithmetic.
>>
>> Actually, no.
Actually, yes.
>> 0.1 in decimal is an infinite repeating sequence in binary floating
>> point. So it is impossible to have enough precision to exactly
>> represent 0.1 (decimal) in binary floating point.
10.0 (0.1 dollars in cents) is equally exact all reasonable implementations
of floating point.
>> "Similarly, the Java or C expression (0.1+0.2==0.3) evaluates to
>> false."
Similarly, the Java or C expression (10.0 + 20.0 == 30.0) evaluates to
true.
>No, it's nothing to do with not being able to represent 0.1 exactly. You
>*know* it's an approximation, but can work with that provided the precision
>is greater than the number of decimal digits you're trying to emulate.
Indeed.
>The following is an example of how it can be done (see main()). Actually,
>you can replace the definition of 'myfloat' with just 'float' instead of
>'double', and it will still work (but up to a smaller magnitude). This code
>emulates some decimal arithmetic with two decimal places. (Note that the
>normal 0.1+0.2==0.3 can give True with some compilers.)
Giving True is probably a compiler bug. The addition may be evaluated
in extra precision in C, but then its result has even less chance of being
accidentally equal to the double precision 0.3. It is probably a compiler
bug to evaluate any of the double precision constants in extra precision.
Buggy compilers like to misevaluate such expressions at compile time using
different rounding precisions and rounding modes than apply at runtime.
C's rules for when the compiler is permitted to evaluate at compile time
using defaults for rounding are delicate.
>/* Floating emulation of fixed point decimal arithmetic */
Too complicated. Just do everything in whole cents (or whatever the
minimal unit in the currency is). In C, require C99 or later, with
IEEE754 support (otherwise you cannot even depend on 1.0 + 1.0 being
2.0). Use fenv to initialize the FP environment suitably. Almost
all calculations need to be exact in cents, possibly after rounding
to cents according to financial rules. Use fenv to check for inexact
results (except in cases where they the intermediate calculations are
expected to be inexact).
>#include <stdio.h>
>#include <stdlib.h>
>#include <math.h>
>
>#define decimals 2
>#define rounding 0.005
>#define factor 100.0
>//#define myfloat float
>#define myfloat double
>
>myfloat round_dec(myfloat x){
>if (x>0.0)
> return floor((x+rounding)*factor)/factor;
>else
> if (x>-rounding) return 0.0;
> return ceil((x-rounding)*factor)/factor;
>}
This only works when the error in the FP calculations is slightly less
than 0.5 cents. One URL pointed to in this thread gives an example
where adding 0.5 to round up half-way cases doesn't work as expected,
because some expression like 0.49999... + 0.5 gives 1.0 after rounding.
Interest rate calculations are one source of half-way cases. The
interest rate is presumably specified as a decimal fraction, say
5%/year. Suppose the principal is $1.10. The interest in infinite
precision is 5.5 cents. This must be rounded according to
financial rules. I don't know what they are, but presumably they
favour bankers, so it is down to 5 cents. Suppose you calculated
the principal dollars an have a tiny error, so it is $1.10000...1.
Then the interest calculation gives 5.50000...5 cents. This is
above the half-way point, so hopefully it is not rounded in the
banker's favour and is rounded up to 6 cents. However, that would
be illegal since the error is in the calculation.
If the financial rules are actually to always round up or down to
cents, then you get the rounding problem whole cents instead of
half-way, and it is practically impossible to round correctly
since no error bound except 0 is sharp enough.
The above is similar to C99's round(). round() just has factor = 1.
Some implementations of round() look similar, but are a bit more
careful to avoid the rounding error for 0.49999... + 0.5 and to
get a specific rounding for exactly half-way cases.
C90 only has rint(). rint() is a bit harder to use, especially in
C90, since it rounds in the current mode and C90 gives no control
over what that is. But in C99 with IEEE754 support you can use
fesetround() to set a known suitable rounding mode. rint() with
rounding to nearest mode is the same as round() (round() is mode-
independent), except for half-way cases, where half-way is half-
way between integers here. Neither of them is any more likely
than the above to match the financial rules (if any) for half-way
cases:
- for rint(), the rounding is machine-dependent (typically, to
even, so that +-0.5 is rounded to +-0 and +-1.5 is rounded to +-2).
- for round(), the rounding is always towards (+-infinity) (so
that +-0.5 is rounded to +-1 and +-1.5 is rounded to +-2).
Working in cents doesn't completely eliminate the problems. Adding up
cents is exact up to $90 trillion in IEEE754 double precision. If
that is not enough, upgrade to 1980s technology with Intel 8087
extended precision. This works up to $184467 trillion. But interest
rate calculations need to first calculate fractional cents, then
round according to financial rules. This seems too hard to do without
doing the first calculation exactly. This is easy to do by working
in units of decimal fractions of cents for doing the interest rate
calculations. E.g., for 5% interest, use hundredths of a cent, and
for 5.68725% interest, use millionths of a cent.
Note that decimal FP only simplifies the interest rate calculations if
there are plenty of decimal digits and the rounding mode matches the
financial rounding rules. Otherwise, there are the following problems:
- as above with $1.10 at 5% interest giving 5.5 cents. Decimal FP
gives 5.5 without the complication of working with cents. But you
have to use funancial rules and not necessarily the machines FP rules
to round this
- the machine's precision (now in decimal digits) must have plenty of
to spare for multiplying by interest rates with many significant
digits. 8 more for multiplying by 5.68725% = 0.0568725. So FP that
can handle up to $90 trillion for adding up cents can only handle
up to $900 thousand for this interest calculation. I guess the
financial rules disallow even more exotic interest rates like
5.68725187171771777171000003888 that would challenge everyone's
software.
Decimal precision is less efficient, so it would cost more for the same
effective range. E.g., the above calculations show that binary 53 bit
precision is no enough, since it only goes up to $900k for the moderately
exotic interest rate. Binary 64 bit precision goes up to $120 trillion,
so it can handle the world's GDP again. Decimal needs 2+12+8 = 21
digits to go up to $100 trillion with the exotic precision. 21 decimal
digits take about 64 binary bits, but only in a binary encoding. I
think practical implementations in hardware would take a few more
binary and cost more.
Bruce
[toc] | [prev] | [next] | [standalone]
| From | "BartC" <bc@freeuk.com> |
|---|---|
| Date | 2014-05-14 12:58 +0100 |
| Message-ID | <jUIcv.37987$ub6.35971@fx32.am4> |
| In reply to | #2799 |
"Bruce Evans" <bde@besplex.bde.org> wrote in message
news:lkvgvv$19v$1@dont-email.me...
> In article <JJtcv.95786$Sp6.12404@fx15.am4>, BartC <bc@freeuk.com> wrote:
>>"Rich" <rich@example.com> wrote in message
>>news:537246b1$0$59749$c3e8da3$e074e489@news.astraweb.com...
>>> BartC <bc@freeuk.com> wrote:
>>
>>>> Given enough precision, I believe that binary floating point can
>>>> emulate what can be done in decimal arithmetic.
>>>
>>> Actually, no.
>
> Actually, yes.
>
>>> 0.1 in decimal is an infinite repeating sequence in binary floating
>>> point. So it is impossible to have enough precision to exactly
>>> represent 0.1 (decimal) in binary floating point.
>
> 10.0 (0.1 dollars in cents) is equally exact all reasonable
> implementations
> of floating point.
So what? You don't use the primitive '=' (or '==' in C) between floating
point values when you know the results are not absolutely precise.
>>The following is an example of how it can be done (see main()). Actually,
>>you can replace the definition of 'myfloat' with just 'float' instead of
>>'double', and it will still work (but up to a smaller magnitude). This
>>code
>>emulates some decimal arithmetic with two decimal places. (Note that the
>>normal 0.1+0.2==0.3 can give True with some compilers.)
>
> Giving True is probably a compiler bug.
Not really. Probably just a coincidence. For example, if any constant 0.1 to
0.9 in the code is constructed as a multiple of 0.1, then it could well be
the case that 0.1+0.2 has exactly the same representation as 0.3.
>>/* Floating emulation of fixed point decimal arithmetic */
>
> Too complicated. Just do everything in whole cents (or whatever the
> minimal unit in the currency is).
The emulation could have used whole units, sure, with input or output scaled
by the right number of decimal places. But it was tidier in this simple demo
to have the stored floating point value be the same as the emulated decimal
without scaling. Also you can use floating point constants within the code
as 0.1 without a scale function needed.
> In C, require C99 or later, with
> IEEE754 support (otherwise you cannot even depend on 1.0 + 1.0 being
> 2.0).
That sounds like a bad implementation, but shouldn't effect the results of
programs like this.
>>myfloat round_dec(myfloat x){
>>if (x>0.0)
>> return floor((x+rounding)*factor)/factor;
>>else
>> if (x>-rounding) return 0.0;
>> return ceil((x-rounding)*factor)/factor;
>>}
>
> This only works when the error in the FP calculations is slightly less
> than 0.5 cents.
That's the trick. If you are emulating some hardware or software that always
has intermediate results with two decimal places (as in my example), then
you do the same. For simple addition or subtraction, you might have to do
large numbers of successive operations, each without rounding, before the
cumulative error approaches 0.005.
With intermediate rounding at each step, the error will rarely be that
large.
> One URL pointed to in this thread gives an example
> where adding 0.5 to round up half-way cases doesn't work as expected,
> because some expression like 0.49999... + 0.5 gives 1.0 after rounding.
Yes there are issues with rounding where a result is exactly between two
possible values. I mention that in another post.
> Interest rate calculations are one source of half-way cases. The
> interest rate is presumably specified as a decimal fraction, say
> 5%/year. Suppose the principal is $1.10. The interest in infinite
> precision is 5.5 cents. This must be rounded according to
> financial rules. I don't know what they are, but presumably they
> favour bankers, so it is down to 5 cents. Suppose you calculated
> the principal dollars an have a tiny error, so it is $1.10000...1.
> Then the interest calculation gives 5.50000...5 cents. This is
> above the half-way point, so hopefully it is not rounded in the
> banker's favour and is rounded up to 6 cents. However, that would
> be illegal since the error is in the calculation.
Floating point gives you the opportunity to round to either 5.0 or 6.0
cents, it doesn't really matter, and remember the approximate 0.5 cents and
add it to next year's interest. Nobody loses out in the long run. Decimal
fixed point can end up discarding some fractions of a cent completely.
Unless you use decimal floating point, then you have the same rounding
problems.
But to solve the above problem, requires a bit more thought. For example, if
interest rates are quoted to a resolution of 0.1% (ie. 0.001), and principal
amounts to $0.01, then any such calculation can only give results to 5
decimal places (but I'm not a mathematician so cannot say for certain).
In other words, any result must be to the nearest $0.00001. Provided there
is enough floating point precision in reserve, it can make use of this fact
to apply the right kind of rounding.
In your example, in one instance I got a result of $0.05500000000000000700,
rounded to 0.05500 (to 1/1000 of a cent). Now I can apply a rounding
function more confidently: any value less than 0.054995 can be rounded down
to 0.05000, and above 0.055005 to 0.06000, assuming rounding rules are to
the nearest cent. But I now have a window within which the interest rate
calculation is expected to be, and that gives me leaway for any FP
inaccuracies.
--
Bartc
[toc] | [prev] | [next] | [standalone]
Page 2 of 3 — ← Prev page 1 [2] 3 Next page →
Back to top | Article view | comp.misc
csiph-web