|
web
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
When double precision isn't very precisepayments to show a running balance on someone's ledger. Our QA team reported that it is producing the wrong balances, and sure enough it was. The answers were coming back with umpteen decimal places written in scientific notation, e.g. 1.23456E-9. I thought I'd play it smart and wrote a function to do all the work in integers - it receives the running balance and new amount, multiplies them by 100 into integer variables, adds the two integers, and divides the result by 100. It's stupid that I have to do this because our state- of-the-art computer can't add two-place numbers together and come up with the right answer, but at least it was an easy enough kludge. Now it turns out it's also converting to integers wrong. For example, with a balance of $595.17 added to $80.00, the new balance is $675.16 because it multiplied 595.17 * 100 and came up with... 59516. The balance and amount are both double precision, so I did some testing: Module FloatTest Sub Main() Dim nFloat1 As Single Dim nFloat2 As Double Dim nInt1 As Integer Dim nInt2 As Integer nFloat1 = 595.17 nInt1 = Int(nFloat1 * 100) Console.WriteLine("Int of single " & nFloat1 & " * 100 is " & nInt1) nFloat2 = 595.17 nInt2 = Int(nFloat2 * 100) Console.WriteLine("Int of double " & nFloat2 & " * 100 is " & nInt2) End Sub End Module The results? Multiply a single-precision number with two decimal places by 100, and you get the right answer (in this case, 59517). Multiply a double precision number by 100 and you get the wrong answer (59516). I know FP math produced weird results on old CPUs (8086 through 80486), but I would have thought for sure some processor genius would have fixed the problem by now. Is this a known bug, or am I using the wrong data types for my purposes, or what? -- Peter B. Steiger Cheyenne, WY If you must reply by email, you can reach me by placing zeroes where you see stars: wypbs.**1 at gmail.com. Hello, Peter,
No, this is not a bug, but for floating point numbers this behaviour that you are seeing is by design. Please see: http://docs.sun.com/source/806-3568/ncg_goldberg.html for a detailed explanation. The data type that you probably want to be using is Decimal. Cheers, Randy Show quoteHide quote "Peter B. Steiger" wrote: > I wrote a quick-and-dirty accounting routine that added up charges and > payments to show a running balance on someone's ledger. Our QA team > reported that it is producing the wrong balances, and sure enough it was. > The answers were coming back with umpteen decimal places written in > scientific notation, e.g. 1.23456E-9. > > I thought I'd play it smart and wrote a function to do all the work in > integers - it receives the running balance and new amount, multiplies > them by 100 into integer variables, adds the two integers, and divides > the result by 100. It's stupid that I have to do this because our state- > of-the-art computer can't add two-place numbers together and come up with > the right answer, but at least it was an easy enough kludge. > > Now it turns out it's also converting to integers wrong. For example, > with a balance of $595.17 added to $80.00, the new balance is $675.16 > because it multiplied 595.17 * 100 and came up with... 59516. > > The balance and amount are both double precision, so I did some testing: > Module FloatTest > Sub Main() > Dim nFloat1 As Single > Dim nFloat2 As Double > Dim nInt1 As Integer > Dim nInt2 As Integer > > nFloat1 = 595.17 > nInt1 = Int(nFloat1 * 100) > Console.WriteLine("Int of single " & nFloat1 & " * 100 is " & nInt1) > nFloat2 = 595.17 > nInt2 = Int(nFloat2 * 100) > Console.WriteLine("Int of double " & nFloat2 & " * 100 is " & nInt2) > End Sub > End Module > > The results? Multiply a single-precision number with two decimal places > by 100, and you get the right answer (in this case, 59517). Multiply a > double precision number by 100 and you get the wrong answer (59516). > > I know FP math produced weird results on old CPUs (8086 through 80486), > but I would have thought for sure some processor genius would have fixed > the problem by now. Is this a known bug, or am I using the wrong data > types for my purposes, or what? > > -- > Peter B. Steiger > Cheyenne, WY > If you must reply by email, you can reach me by placing zeroes > where you see stars: wypbs.**1 at gmail.com. > On Tue, 19 May 2009 16:40:01 -0700, OmegaSquared sez:
> No, this is not a bug, but for floating point numbers this behaviour Thanks! I'll certainly make the change... but that article didn't do > that you are seeing is by design. Please see: > > http://docs.sun.com/source/806-3568/ncg_goldberg.html > > for a detailed explanation. > > The data type that you probably want to be using is Decimal. much to convince me "that's not a bug, it's a feature." If single- or double-precision floating point variables don't perform basic arithmetic correctly, what IS an appropriate (and reliable) use for them? -- Peter B. Steiger Cheyenne, WY If you must reply by email, you can reach me by placing zeroes where you see stars: wypbs.**1 at gmail.com.
Show quote
Hide quote
"Peter B. Steiger" <see.sig@for.email.address> wrote in message Base 2 numbers, which is what computers use, cannot precisely represent Base news:3eydnWCzoONg14nXnZ2dnUVZ_jJi4p2d@bresnan.com... > On Tue, 19 May 2009 16:40:01 -0700, OmegaSquared sez: > >> No, this is not a bug, but for floating point numbers this behaviour >> that you are seeing is by design. Please see: >> >> http://docs.sun.com/source/806-3568/ncg_goldberg.html >> >> for a detailed explanation. >> >> The data type that you probably want to be using is Decimal. > > Thanks! I'll certainly make the change... but that article didn't do > much to convince me "that's not a bug, it's a feature." If single- or > double-precision floating point variables don't perform basic arithmetic > correctly, what IS an appropriate (and reliable) use for them? > > -- > Peter B. Steiger > Cheyenne, WY > If you must reply by email, you can reach me by placing zeroes > where you see stars: wypbs.**1 at gmail.com. > 10 numbers, which is what humans use. You have a gap in your understanding of how computers do arithmetic. Basically, there are three systems - whole numbers, which are exactly represented within the valid range of the machine word size, packed or binary coded decimals, which can be exactly represented within the valid range of the machine's packed decimal, and floats, which can be exactly represented if and only if there is a non-infinite mathematical expansion of the base 10 to base 2 conversion for the number that fits inside the machine's floating number word size. In dotNet, these translate into whole numbers - System.Int16, System.Int32, and System.Int64 and their unsigned variants - arithmetic on these values is relatively simple as most CPUs directly support it. packed decimals - System.Decimal - The x86 line of processors has had direct support for since the 8086 and 8088 in the binary coded decimal instructions. The 8087 extended the range. floats - Single and Double - the 8087 and it's descendents support the IEEE definitions for these types. Starting with 80486 this support was built in to the main CPU. The issue you feel is a bug is actually a limitation in _ALL_ current computing hardware. Languages that provide "exact" values for floating point numbers don't directly use the hardware's floating point support. Instead, they split the number into chunks that can be directly handled by the packed decimal hardware and do the arithmetic using the rules for carrying and borrowing we all learn in grade school. Mike Ober.
Show quote
Hide quote
"Peter B. Steiger" <see.sig@for.email.address> wrote in message It's not a feature or a bug. It's a fact of binary arithmetic; some news:3eydnWCzoONg14nXnZ2dnUVZ_jJi4p2d@bresnan.com... > On Tue, 19 May 2009 16:40:01 -0700, OmegaSquared sez: > >> No, this is not a bug, but for floating point numbers this behaviour >> that you are seeing is by design. Please see: >> >> http://docs.sun.com/source/806-3568/ncg_goldberg.html >> >> for a detailed explanation. >> >> The data type that you probably want to be using is Decimal. > > Thanks! I'll certainly make the change... but that article didn't do > much to convince me "that's not a bug, it's a feature." If single- or > double-precision floating point variables don't perform basic arithmetic > correctly, what IS an appropriate (and reliable) use for them? > > -- > Peter B. Steiger > Cheyenne, WY > If you must reply by email, you can reach me by placing zeroes > where you see stars: wypbs.**1 at gmail.com. fractions can not be precisely represented in binary. Just as some cannot be precisely represented in decimal - 1/3 for example. Except for extremely rare bugs computers perform arithmetic correctly. You just have to know which kind of arithmetic, binary or decimal, to ask for. Bob On Wed, 20 May 2009 20:11:52 -0400, eBob.com sez:
> It's not a feature or a bug. It's a fact of binary arithmetic; some Fair enough - thanks to Bob and Michael Ober for the explanation. I do > fractions can not be precisely represented in binary. Just as some > cannot be precisely represented in decimal - 1/3 for example. Except > for extremely rare bugs computers perform arithmetic correctly. You > just have to know which kind of arithmetic, binary or decimal, to ask > for. understand the way computers use binary; I just thought that all the "magic" to convert to base 10 happened internally in the CPU as requested by assembler calls. But hey, I'm an end user application developer - I don't think about what goes on under the hood. So under what circumstances would single & double precision floats be the appropriate choice when you could count on accuracy to what MS claims to be 4.a-bunch-of-numbersE-324? What kind of operations (and values) can use those data types safely? -- Peter B. Steiger Cheyenne, WY If you must reply by email, you can reach me by placing zeroes where you see stars: wypbs.**1 at gmail.com.
Show quote
Hide quote
"Peter B. Steiger" <see.sig@for.email.address> wrote in message For Double, only the first 15 digits of the answer are guaranteed. The last news:SbidnfF7T7zOL4jXnZ2dnUVZ_uli4p2d@bresnan.com... > On Wed, 20 May 2009 20:11:52 -0400, eBob.com sez: > >> It's not a feature or a bug. It's a fact of binary arithmetic; some >> fractions can not be precisely represented in binary. Just as some >> cannot be precisely represented in decimal - 1/3 for example. Except >> for extremely rare bugs computers perform arithmetic correctly. You >> just have to know which kind of arithmetic, binary or decimal, to ask >> for. > > Fair enough - thanks to Bob and Michael Ober for the explanation. I do > understand the way computers use binary; I just thought that all the > "magic" to convert to base 10 happened internally in the CPU as requested > by assembler calls. But hey, I'm an end user application developer - I > don't think about what goes on under the hood. > > So under what circumstances would single & double precision floats be the > appropriate choice when you could count on accuracy to what MS claims to > be 4.a-bunch-of-numbersE-324? What kind of operations (and values) can > use those data types safely? > > -- > Peter B. Steiger > Cheyenne, WY > If you must reply by email, you can reach me by placing zeroes > where you see stars: wypbs.**1 at gmail.com. > two digits are referred to as guard digits and will almost never be accurate. For Single, 7 digits are guaranteed. Again the last two digits are guard digits. As another poster pointed out, if you must have precise answers, use System.Decimal. As long as the fractional part of the number can be exactly represented in four base 10 digits or less, System.Decimal will not have rounding errors. Mike. Peter B. Steiger wrote:
Show quoteHide quote > On Tue, 19 May 2009 16:40:01 -0700, OmegaSquared sez: Single/Double can be considered as "analog" values. For example, if you> >> No, this is not a bug, but for floating point numbers this behaviour >> that you are seeing is by design. Please see: >> >> http://docs.sun.com/source/806-3568/ncg_goldberg.html >> >> for a detailed explanation. >> >> The data type that you probably want to be using is Decimal. > > Thanks! I'll certainly make the change... but that article didn't do > much to convince me "that's not a bug, it's a feature." If single- or > double-precision floating point variables don't perform basic > arithmetic correctly, what IS an appropriate (and reliable) use for > them? store coordinates in 3D space, it doesn't matter if the deviation (due to finite storage space) is positive or negativ. Math.PI cam also not be stored exactly and you can calculate well with it without caring if the actual PI is a little bit smaller or larger than Math.PI. Armin Armin Zingler wrote:
> Single/Double can be considered as "analog" values. Isn't that the wrong way round? An analog variable can take any value, like the groove on a vinyl record, whereas a digital value can only take discreet values, like the sounds on a CD. > For example, if you store coordinates in 3D space, it doesn't matter if I don't understand how that follows, but then again I finish work in a few > the deviation (due to finite storage space) is positive or negativ. minutes so my brain may be elsewhere. A Decimal just happens to be able to take and manipulate values in base 10, which is what the OP needed to find out. Andrew Andrew Morton wrote:
> Armin Zingler wrote: As we don't have analog variables, a Double variable is the most often used>> Single/Double can be considered as "analog" values. > > Isn't that the wrong way round? An analog variable can take any > value, like the groove on a vinyl record, whereas a digital value can > only take discreet values, like the sounds on a CD. type to store an analog value. That means a value of which you don't care about the number of decimal/octal/whatever digits necessary to display the value as a String. >> For example, if you store coordinates in 3D space, it doesn't matter In the example of the OP's first post, the Double value was a little bit>> if the deviation (due to finite storage space) is positive or >> negativ. > > I don't understand how that follows, smaller than the value expected. If you cut the fractional part, you get the "wrong" result. Therefore his criticism/question about the Double data type (in opposite to Single). If one considers a Double variable as a place to store an analog value as close as possible, it also doesn't matter anymore if the stored value is smaller or greater than the actual value. > but then again I finish work in Absolutely, but my answer was to his question what a double value can be> a few minutes so my brain may be elsewhere. :-) > A Decimal just happens to be able to take and manipulate values in > base 10, which is what the OP needed to find out. used for at all. Armin Peter,
The double is not meant to be used in financial computing. This is not even by design, this is simple general used behaviour. For accounting is the decimal meant. Be aware that standard in Net ISO rounding (banking rounding is used) Cor Show quoteHide quote "Peter B. Steiger" <see.sig@for.email.address> wrote in message news:8d-dnVDaj4fyoo7XnZ2dnUVZ_j1i4p2d@bresnan.com... >I wrote a quick-and-dirty accounting routine that added up charges and > payments to show a running balance on someone's ledger. Our QA team > reported that it is producing the wrong balances, and sure enough it was. > The answers were coming back with umpteen decimal places written in > scientific notation, e.g. 1.23456E-9. > > I thought I'd play it smart and wrote a function to do all the work in > integers - it receives the running balance and new amount, multiplies > them by 100 into integer variables, adds the two integers, and divides > the result by 100. It's stupid that I have to do this because our state- > of-the-art computer can't add two-place numbers together and come up with > the right answer, but at least it was an easy enough kludge. > > Now it turns out it's also converting to integers wrong. For example, > with a balance of $595.17 added to $80.00, the new balance is $675.16 > because it multiplied 595.17 * 100 and came up with... 59516. > > The balance and amount are both double precision, so I did some testing: > Module FloatTest > Sub Main() > Dim nFloat1 As Single > Dim nFloat2 As Double > Dim nInt1 As Integer > Dim nInt2 As Integer > > nFloat1 = 595.17 > nInt1 = Int(nFloat1 * 100) > Console.WriteLine("Int of single " & nFloat1 & " * 100 is " & nInt1) > nFloat2 = 595.17 > nInt2 = Int(nFloat2 * 100) > Console.WriteLine("Int of double " & nFloat2 & " * 100 is " & nInt2) > End Sub > End Module > > The results? Multiply a single-precision number with two decimal places > by 100, and you get the right answer (in this case, 59517). Multiply a > double precision number by 100 and you get the wrong answer (59516). > > I know FP math produced weird results on old CPUs (8086 through 80486), > but I would have thought for sure some processor genius would have fixed > the problem by now. Is this a known bug, or am I using the wrong data > types for my purposes, or what? > > -- > Peter B. Steiger > Cheyenne, WY > If you must reply by email, you can reach me by placing zeroes > where you see stars: wypbs.**1 at gmail.com. >Be aware that standard in Net ISO rounding (banking rounding is used) every computer language i know of does bankers rounding this includes even Fortran and COBOL most people are just not aware of that fact , so it is not something specific to VB or .Net ( just wanted to make that clear ) However in all those languages ( even COBOL ) it is possible to use common rounding in .Net you do that with system.math.round and the away from zero option "By default, Math.Round uses MidpointRounding.ToEven. Most people are not familiar with "rounding to even" as the alternative, "rounding away from zero" is more commonly taught in school. .NET defaults to "Rounding to even" as it is statistically superior because it doesn't share the tendency of "rounding away from zero" to round up slightly more often than it rounds down (assuming the numbers being rounded tend to be positive.) " HTH Michel Show quoteHide quote "Cor Ligthert[MVP]" <Notmyfirstn***@planet.nl> schreef in bericht news:efL%23KnR2JHA.4416@TK2MSFTNGP05.phx.gbl... > Peter, > > The double is not meant to be used in financial computing. > This is not even by design, this is simple general used behaviour. > > For accounting is the decimal meant. > > Be aware that standard in Net ISO rounding (banking rounding is used) > > Cor > > "Peter B. Steiger" <see.sig@for.email.address> wrote in message > news:8d-dnVDaj4fyoo7XnZ2dnUVZ_j1i4p2d@bresnan.com... >>I wrote a quick-and-dirty accounting routine that added up charges and >> payments to show a running balance on someone's ledger. Our QA team >> reported that it is producing the wrong balances, and sure enough it was. >> The answers were coming back with umpteen decimal places written in >> scientific notation, e.g. 1.23456E-9. >> >> I thought I'd play it smart and wrote a function to do all the work in >> integers - it receives the running balance and new amount, multiplies >> them by 100 into integer variables, adds the two integers, and divides >> the result by 100. It's stupid that I have to do this because our state- >> of-the-art computer can't add two-place numbers together and come up with >> the right answer, but at least it was an easy enough kludge. >> >> Now it turns out it's also converting to integers wrong. For example, >> with a balance of $595.17 added to $80.00, the new balance is $675.16 >> because it multiplied 595.17 * 100 and came up with... 59516. >> >> The balance and amount are both double precision, so I did some testing: >> Module FloatTest >> Sub Main() >> Dim nFloat1 As Single >> Dim nFloat2 As Double >> Dim nInt1 As Integer >> Dim nInt2 As Integer >> >> nFloat1 = 595.17 >> nInt1 = Int(nFloat1 * 100) >> Console.WriteLine("Int of single " & nFloat1 & " * 100 is " & nInt1) >> nFloat2 = 595.17 >> nInt2 = Int(nFloat2 * 100) >> Console.WriteLine("Int of double " & nFloat2 & " * 100 is " & nInt2) >> End Sub >> End Module >> >> The results? Multiply a single-precision number with two decimal places >> by 100, and you get the right answer (in this case, 59517). Multiply a >> double precision number by 100 and you get the wrong answer (59516). >> >> I know FP math produced weird results on old CPUs (8086 through 80486), >> but I would have thought for sure some processor genius would have fixed >> the problem by now. Is this a known bug, or am I using the wrong data >> types for my purposes, or what? >> >> -- >> Peter B. Steiger >> Cheyenne, WY >> If you must reply by email, you can reach me by placing zeroes >> where you see stars: wypbs.**1 at gmail.com. > Michel,
I have really made endless programs in past in Cobol for different systems. I am me not aware that bankers rounding was used in the first ones. We simply had to do that forever ourselves. But maybe there are versions who do. Are you telling in Albert Hein as well that they should round to even. That it is better I know for a long time, but tell it to all the end-users of your company But thanks for the information :-) CorShow quoteHide quote "Michel Posseth [MCP]" <M***@posseth.com> wrote in message news:Oa7Nn%23e2JHA.2656@TK2MSFTNGP05.phx.gbl... > >Be aware that standard in Net ISO rounding (banking rounding is used) > > every computer language i know of does bankers rounding this includes even > Fortran and COBOL > most people are just not aware of that fact , so it is not something > specific to VB or .Net > > ( just wanted to make that clear ) > > > However in all those languages ( even COBOL ) it is possible to use common > rounding in .Net you do that with system.math.round > and the away from zero option > > "By default, Math.Round uses MidpointRounding.ToEven. Most people are not > familiar with "rounding to even" as the alternative, "rounding away from > zero" is more commonly taught in school. .NET defaults to "Rounding to > even" as it is statistically superior because it doesn't share the > tendency of "rounding away from zero" to round up slightly more often than > it rounds down (assuming the numbers being rounded tend to be positive.) " > > > HTH > > Michel > > > "Cor Ligthert[MVP]" <Notmyfirstn***@planet.nl> schreef in bericht > news:efL%23KnR2JHA.4416@TK2MSFTNGP05.phx.gbl... >> Peter, >> >> The double is not meant to be used in financial computing. >> This is not even by design, this is simple general used behaviour. >> >> For accounting is the decimal meant. >> >> Be aware that standard in Net ISO rounding (banking rounding is used) >> >> Cor >> >> "Peter B. Steiger" <see.sig@for.email.address> wrote in message >> news:8d-dnVDaj4fyoo7XnZ2dnUVZ_j1i4p2d@bresnan.com... >>>I wrote a quick-and-dirty accounting routine that added up charges and >>> payments to show a running balance on someone's ledger. Our QA team >>> reported that it is producing the wrong balances, and sure enough it >>> was. >>> The answers were coming back with umpteen decimal places written in >>> scientific notation, e.g. 1.23456E-9. >>> >>> I thought I'd play it smart and wrote a function to do all the work in >>> integers - it receives the running balance and new amount, multiplies >>> them by 100 into integer variables, adds the two integers, and divides >>> the result by 100. It's stupid that I have to do this because our >>> state- >>> of-the-art computer can't add two-place numbers together and come up >>> with >>> the right answer, but at least it was an easy enough kludge. >>> >>> Now it turns out it's also converting to integers wrong. For example, >>> with a balance of $595.17 added to $80.00, the new balance is $675.16 >>> because it multiplied 595.17 * 100 and came up with... 59516. >>> >>> The balance and amount are both double precision, so I did some testing: >>> Module FloatTest >>> Sub Main() >>> Dim nFloat1 As Single >>> Dim nFloat2 As Double >>> Dim nInt1 As Integer >>> Dim nInt2 As Integer >>> >>> nFloat1 = 595.17 >>> nInt1 = Int(nFloat1 * 100) >>> Console.WriteLine("Int of single " & nFloat1 & " * 100 is " & nInt1) >>> nFloat2 = 595.17 >>> nInt2 = Int(nFloat2 * 100) >>> Console.WriteLine("Int of double " & nFloat2 & " * 100 is " & nInt2) >>> End Sub >>> End Module >>> >>> The results? Multiply a single-precision number with two decimal places >>> by 100, and you get the right answer (in this case, 59517). Multiply a >>> double precision number by 100 and you get the wrong answer (59516). >>> >>> I know FP math produced weird results on old CPUs (8086 through 80486), >>> but I would have thought for sure some processor genius would have fixed >>> the problem by now. Is this a known bug, or am I using the wrong data >>> types for my purposes, or what? >>> >>> -- >>> Peter B. Steiger >>> Cheyenne, WY >>> If you must reply by email, you can reach me by placing zeroes >>> where you see stars: wypbs.**1 at gmail.com. >> > > "Cor Ligthert[MVP]" <Notmyfirstn***@planet.nl> wrote in message That depends what you mean by "better". The most appropriate method of news:u$9GYOh2JHA.6056@TK2MSFTNGP03.phx.gbl... > Are you telling in Albert Hein as well that they should > round to even. That it is better I know for a long time rounding depends on the circumstances and there is not a "one size fits all" best solution. For example, if in the UK you are writing code to calculate how much money an individual owes you in order to send him a bill then you must always "round down" to the nearest penny (currently the lowest value legal tender coin) because rounding up would mean that you are billing him for more than the amount he owes you, an amount to which you are not entitled. And of course there are other different circumstances in which the correct solution is the opposite (always rounding up to the nearest penny). Many other circumstances would require you to perform bankers' rounding, or some other form of rounding, depending on exactly what task you were performing. As with most things, it's "horses for courses". Mike Mike,
I'll change "better" in typical (real) English. It is more cricket (I don't know if I write this correct or even if it is croquet, but I say it like that) :-) CorShow quoteHide quote "Mike Williams" <M***@WhiskyAndCoke.com> wrote in message news:uf4mu5i2JHA.3304@TK2MSFTNGP06.phx.gbl... > "Cor Ligthert[MVP]" <Notmyfirstn***@planet.nl> wrote in message > news:u$9GYOh2JHA.6056@TK2MSFTNGP03.phx.gbl... > >> Are you telling in Albert Hein as well that they should >> round to even. That it is better I know for a long time > > That depends what you mean by "better". The most appropriate method of > rounding depends on the circumstances and there is not a "one size fits > all" best solution. For example, if in the UK you are writing code to > calculate how much money an individual owes you in order to send him a > bill then you must always "round down" to the nearest penny (currently the > lowest value legal tender coin) because rounding up would mean that you > are billing him for more than the amount he owes you, an amount to which > you are not entitled. And of course there are other different > circumstances in which the correct solution is the opposite (always > rounding up to the nearest penny). Many other circumstances would require > you to perform bankers' rounding, or some other form of rounding, > depending on exactly what task you were performing. As with most things, > it's "horses for courses". > > Mike > > > Hello Cor ,
> I have really made endless programs in past in Cobol for different Well this doesn`t surprise me as my 2 COBOL co workers who worked for 30 > systems. > I am me not aware that bankers rounding was used in the first ones. > We simply had to do that forever ourselves. > > But maybe there are versions who do. years in the industry where also stating that it wasn`t like that in COBOL untill i showed them a simple calculation an challenged them to do the same in COBOL , it turned out that i was right and there COBOL production system used bankers rounding ( as allmost all program languages do by default ) This isn`t a bad thing however you must be aware of it when you perform certain calculations This is knowledge that i feel should be in every standard programming course , but as i noticed in practice i still tell my new co workers something new even if they worked for years in the industry and hold multiple certifications or even have university degrees :-( . I learned it from my tutor in the first week i started to become a commercial programmer ( i had a on the job training from a verry experienced developer , who wrote on the core modules of the EXACT corporation http://www.exactsoftware.com ) and already then ( 1998 ) he told me that 95% of the coders are not aware of that simple fact . > Are you telling in Albert Hein as well that they should round to even. No Midpoint rounding away from zero that is something different as just > That it is better I know for a long time, but tell it to all the end-users > of your company rounding to even , for a fact "Midpoint rounding away from zero" is rounding how it is tought at every elementary school , so i guess that if they wouldn`t use that method on your receipt you would go to the manager and tell them to correct your payment . lets get to the basics A + B = C 2.5 + 3.5 = C with common rounding we get 3 + 4 = 7. with banker's rounding we get 2 + 4 = 6. wich one is correct ? see the problem Albert Heijn `s POS software developer is facing :-) If you always round away from zero you'll always be over. if you round some numbers up and some numbers down you'll be closer to the correct answer. You should NEVER implicitly round numbers if they matter at all. always be explicit if your values really matter. P.S. AFAIK every POS system just rounds the final sum with midpoint rounding away from zero regards Michel Show quoteHide quote "Cor Ligthert[MVP]" <Notmyfirstn***@planet.nl> schreef in bericht news:u$9GYOh2JHA.6056@TK2MSFTNGP03.phx.gbl... > Michel, > > I have really made endless programs in past in Cobol for different > systems. > I am me not aware that bankers rounding was used in the first ones. > We simply had to do that forever ourselves. > > But maybe there are versions who do. > > Are you telling in Albert Hein as well that they should round to even. > That it is better I know for a long time, but tell it to all the end-users > of your company > > But thanks for the information > > :-) > > Cor > > "Michel Posseth [MCP]" <M***@posseth.com> wrote in message > news:Oa7Nn%23e2JHA.2656@TK2MSFTNGP05.phx.gbl... >> >Be aware that standard in Net ISO rounding (banking rounding is used) >> >> every computer language i know of does bankers rounding this includes >> even Fortran and COBOL >> most people are just not aware of that fact , so it is not something >> specific to VB or .Net >> >> ( just wanted to make that clear ) >> >> >> However in all those languages ( even COBOL ) it is possible to use >> common rounding in .Net you do that with system.math.round >> and the away from zero option >> >> "By default, Math.Round uses MidpointRounding.ToEven. Most people are not >> familiar with "rounding to even" as the alternative, "rounding away from >> zero" is more commonly taught in school. .NET defaults to "Rounding to >> even" as it is statistically superior because it doesn't share the >> tendency of "rounding away from zero" to round up slightly more often >> than it rounds down (assuming the numbers being rounded tend to be >> positive.) " >> >> >> HTH >> >> Michel >> >> >> "Cor Ligthert[MVP]" <Notmyfirstn***@planet.nl> schreef in bericht >> news:efL%23KnR2JHA.4416@TK2MSFTNGP05.phx.gbl... >>> Peter, >>> >>> The double is not meant to be used in financial computing. >>> This is not even by design, this is simple general used behaviour. >>> >>> For accounting is the decimal meant. >>> >>> Be aware that standard in Net ISO rounding (banking rounding is used) >>> >>> Cor >>> >>> "Peter B. Steiger" <see.sig@for.email.address> wrote in message >>> news:8d-dnVDaj4fyoo7XnZ2dnUVZ_j1i4p2d@bresnan.com... >>>>I wrote a quick-and-dirty accounting routine that added up charges and >>>> payments to show a running balance on someone's ledger. Our QA team >>>> reported that it is producing the wrong balances, and sure enough it >>>> was. >>>> The answers were coming back with umpteen decimal places written in >>>> scientific notation, e.g. 1.23456E-9. >>>> >>>> I thought I'd play it smart and wrote a function to do all the work in >>>> integers - it receives the running balance and new amount, multiplies >>>> them by 100 into integer variables, adds the two integers, and divides >>>> the result by 100. It's stupid that I have to do this because our >>>> state- >>>> of-the-art computer can't add two-place numbers together and come up >>>> with >>>> the right answer, but at least it was an easy enough kludge. >>>> >>>> Now it turns out it's also converting to integers wrong. For example, >>>> with a balance of $595.17 added to $80.00, the new balance is $675.16 >>>> because it multiplied 595.17 * 100 and came up with... 59516. >>>> >>>> The balance and amount are both double precision, so I did some >>>> testing: >>>> Module FloatTest >>>> Sub Main() >>>> Dim nFloat1 As Single >>>> Dim nFloat2 As Double >>>> Dim nInt1 As Integer >>>> Dim nInt2 As Integer >>>> >>>> nFloat1 = 595.17 >>>> nInt1 = Int(nFloat1 * 100) >>>> Console.WriteLine("Int of single " & nFloat1 & " * 100 is " & nInt1) >>>> nFloat2 = 595.17 >>>> nInt2 = Int(nFloat2 * 100) >>>> Console.WriteLine("Int of double " & nFloat2 & " * 100 is " & nInt2) >>>> End Sub >>>> End Module >>>> >>>> The results? Multiply a single-precision number with two decimal >>>> places >>>> by 100, and you get the right answer (in this case, 59517). Multiply a >>>> double precision number by 100 and you get the wrong answer (59516). >>>> >>>> I know FP math produced weird results on old CPUs (8086 through 80486), >>>> but I would have thought for sure some processor genius would have >>>> fixed >>>> the problem by now. Is this a known bug, or am I using the wrong data >>>> types for my purposes, or what? >>>> >>>> -- >>>> Peter B. Steiger >>>> Cheyenne, WY >>>> If you must reply by email, you can reach me by placing zeroes >>>> where you see stars: wypbs.**1 at gmail.com. >>> >> >> > On Wed, 20 May 2009 09:08:14 +0200, Cor Ligthert[MVP] sez:
> Be aware that standard in Net ISO rounding (banking rounding is used) True, but when we're dealing with whole pennies rounding is not an issue... my original complaint that started this thread involved simply adding two two-decimal numbers together and expecting the result to be correct to two decimal places. As others have noted, the "decimal" (formerly currency) data type is what I need for this. -- Peter B. Steiger Cheyenne, WY If you must reply by email, you can reach me by placing zeroes where you see stars: wypbs.**1 at gmail.com. duh
"Others have noted", what you mean with that, I have written that as well? If you cut out messages then do it correct? Or do you find it normal as I make from your message "Peter B. Steiger" <see.sig@for.email.address> wrote in message Cor>>>True, but we're dealing with pennies ... Show quoteHide quote "Peter B. Steiger" <see.sig@for.email.address> wrote in message news:SbidnfB7T7xGL4jXnZ2dnUVZ_umnnZ2d@bresnan.com... > On Wed, 20 May 2009 09:08:14 +0200, Cor Ligthert[MVP] sez: > >> Be aware that standard in Net ISO rounding (banking rounding is used) > > True, but when we're dealing with whole pennies rounding is not an > issue... my original complaint that started this thread involved simply > adding two two-decimal numbers together and expecting the result to be > correct to two decimal places. As others have noted, the > "decimal" (formerly currency) data type is what I need for this. > > -- > Peter B. Steiger > Cheyenne, WY > If you must reply by email, you can reach me by placing zeroes > where you see stars: wypbs.**1 at gmail.com. On Thu, 21 May 2009 22:22:14 +0200, Cor Ligthert[MVP] sez:
> "Others have noted", what you mean with that, I have written that as No, I mean that I got the answer to my question in replies that other > well? people wrote. I'm sorry if it sounds like I was misquoting you, but I was not. > If you cut out messages then do it correct? I always preserve the exact wording of a message I quote, but I also remove any quoted material that does not relate to my reply... it makes it easier to read the question and answer in a normal conversational flow. Again, I apologize if this upsets you. If you find a place where I misquoted you, please let me know. > Or do you find it normal as I make from your message Sure, that works fine. You quoted me accurately; the next step would be > "Peter B. Steiger" <see.sig@for.email.address> wrote in message >>>>True, but we're dealing with pennies ... to follow that quote with any comments you have that relate to the part you quoted. It turns out there is a name for the reply style I use - I did not know that! It's called interleaved, or inline, quoting: http://en.wikipedia.org/wiki/Posting_style (no relation to the "Peter" used in the examples). HTH. -- Peter B. Steiger Cheyenne, WY If you must reply by email, you can reach me by placing zeroes where you see stars: wypbs.**1 at gmail.com. Peter
I wrote this quiet early >For accounting is the decimal meant. The only "other" who wrote that before me was Michael D OberI wrote it to show, that I agreed with him. Your message can give the idea that I disagreed with him. Cor Show quoteHide quote "Peter B. Steiger" <see.sig@for.email.address> wrote in message news:E4KdnauNxvsbVojXnZ2dnUVZ_o9i4p2d@bresnan.com... > On Thu, 21 May 2009 22:22:14 +0200, Cor Ligthert[MVP] sez: >> "Others have noted", what you mean with that, I have written that as >> well? > > No, I mean that I got the answer to my question in replies that other > people wrote. I'm sorry if it sounds like I was misquoting you, but I > was not. > >> If you cut out messages then do it correct? > > I always preserve the exact wording of a message I quote, but I also > remove any quoted material that does not relate to my reply... it makes > it easier to read the question and answer in a normal conversational > flow. Again, I apologize if this upsets you. If you find a place where I > misquoted you, please let me know. > > >> Or do you find it normal as I make from your message >> "Peter B. Steiger" <see.sig@for.email.address> wrote in message >>>>>True, but we're dealing with pennies ... > > Sure, that works fine. You quoted me accurately; the next step would be > to follow that quote with any comments you have that relate to the part > you quoted. > > It turns out there is a name for the reply style I use - I did not know > that! It's called interleaved, or inline, quoting: > http://en.wikipedia.org/wiki/Posting_style (no relation to the "Peter" > used in the examples). > > HTH. > > -- > Peter B. Steiger > Cheyenne, WY > If you must reply by email, you can reach me by placing zeroes > where you see stars: wypbs.**1 at gmail.com. "Peter B. Steiger" <see.sig@for.email.address> wrote in message It isn't if you're adding and subtracting them but it is if you are news:SbidnfB7T7xGL4jXnZ2dnUVZ_umnnZ2d@bresnan.com... > True, but when we're dealing with whole pennies > rounding is not an issue... performing other operations, such as calculating sales tax or VAT or performing other similar operations. Mike Peter:
While the response from other writter is correct in advising that you should not be using floating point calculations for financial analysis, you are also correct that there is a bug in the floating point arithmetic in VB.Net. The symptom is that when you add two double precision variables together and assign the result to another double precision variable, the result may only be accurate to single precision. The remaining digits are random. This behavior does not occur all of the time however. It seems to depend on what has preceeded the calculation. I have seen this in my own code under repeatable conditions, and it has been verified by a co-worker who encountered the same problem independently in a different program. The code below is a simple subroutine that will test whether the error is occurring. Just call this from anywhere in your program. I find that sometimes this test routine passes, and sometimes it fails and traps an error with the message box. I have not determined any way to determine if/when the error will occur. This is truely a serious problem that makes VB inadequate for certain types of engineering calculations where double precision is important. I have tried converting some my code to use the Decimal data type, but that actually made the problem worse. It is not practical to convert my entire program to Decimal, so it is an unresolved problem at this point. Oddly, the problem seems related to the assignment of the value to a variable. If you set a break point in this routine and inspect the expression in the watch window it will be correct, but the value of the variable that the expression is assigned to is not correct. Public Shared Sub TestAddition() Dim dummy1 As Double, dummy2 As Double, dummy3 As Double Dim dummy4 As Double Dim dummy5 As Double dummy1 = 1.0 / 3.0 dummy2 = 1.0 dummy3 = dummy1 + dummy2 'should be 1.3333333333333333, but is actually 1.3333333730697632 'Debug.Print(dummy3) dummy4 = 1.0 + 1.0 / 3.0 'this produces the correct answer: 1.3333333333333333; therefore the problem seems to be with adding double-precision variables, not literals 'Debug.Print(dummy4) dummy5 = dummy3 - dummy4 'the difference between the correct and incorrect answers 'Debug.Print(dummy5) If dummy5 > 0.000000001 Then MsgBox("round off error in vb") End If End Sub Show quoteHide quote "Peter B. Steiger" wrote: > I wrote a quick-and-dirty accounting routine that added up charges and > payments to show a running balance on someone's ledger. Our QA team > reported that it is producing the wrong balances, and sure enough it was. > The answers were coming back with umpteen decimal places written in > scientific notation, e.g. 1.23456E-9. > > I thought I'd play it smart and wrote a function to do all the work in > integers - it receives the running balance and new amount, multiplies > them by 100 into integer variables, adds the two integers, and divides > the result by 100. It's stupid that I have to do this because our state- > of-the-art computer can't add two-place numbers together and come up with > the right answer, but at least it was an easy enough kludge. > > Now it turns out it's also converting to integers wrong. For example, > with a balance of $595.17 added to $80.00, the new balance is $675.16 > because it multiplied 595.17 * 100 and came up with... 59516. > > The balance and amount are both double precision, so I did some testing: > Module FloatTest > Sub Main() > Dim nFloat1 As Single > Dim nFloat2 As Double > Dim nInt1 As Integer > Dim nInt2 As Integer > > nFloat1 = 595.17 > nInt1 = Int(nFloat1 * 100) > Console.WriteLine("Int of single " & nFloat1 & " * 100 is " & nInt1) > nFloat2 = 595.17 > nInt2 = Int(nFloat2 * 100) > Console.WriteLine("Int of double " & nFloat2 & " * 100 is " & nInt2) > End Sub > End Module > > The results? Multiply a single-precision number with two decimal places > by 100, and you get the right answer (in this case, 59517). Multiply a > double precision number by 100 and you get the wrong answer (59516). > > I know FP math produced weird results on old CPUs (8086 through 80486), > but I would have thought for sure some processor genius would have fixed > the problem by now. Is this a known bug, or am I using the wrong data > types for my purposes, or what? > > -- > Peter B. Steiger > Cheyenne, WY > If you must reply by email, you can reach me by placing zeroes > where you see stars: wypbs.**1 at gmail.com. > Jeff Dillingham wrote:
> Dim dummy1 As Double, dummy2 As Double, dummy3 As Double Your statement reminded me of an issue I encountered some years ago in a> Dim dummy4 As Double > Dim dummy5 As Double > > dummy1 = 1.0 / 3.0 > dummy2 = 1.0 > dummy3 = dummy1 + dummy2 'should be 1.3333333333333333, > but is actually 1.3333333730697632 different situation. I've search and found it: (in short: Direct3D sets FPU to single precision mode) http://groups.google.com/group/microsoft.public.win32.programmer.directx.managed/browse_frm/thread/10c3ba49a550edc4 Probably, somewhere in your code, maybe in a 3rd party component or if you also use DirectX, the FPU is set to single-precision mode also. If i execute call TestAddition Create Direct3D Device without FPU_Reserve flag call TestAddition I get exactly the behavior you describe. Armin Armin:
Wow! Dude! You are my new best friend. Yes, I use Direct3D in my code. Never occurred to me that was related to the problem. I followed the link you sent me. As advised I now set the FPUPreserve flag when I create the Direct3D device. The problem went away immediately. You have saved me days of headache and anxiety. Thanks much. Jeff Show quoteHide quote "Armin Zingler" wrote: > Jeff Dillingham wrote: > > Dim dummy1 As Double, dummy2 As Double, dummy3 As Double > > Dim dummy4 As Double > > Dim dummy5 As Double > > > > dummy1 = 1.0 / 3.0 > > dummy2 = 1.0 > > dummy3 = dummy1 + dummy2 'should be 1.3333333333333333, > > but is actually 1.3333333730697632 > > > Your statement reminded me of an issue I encountered some years ago in a > different situation. I've search and found it: (in short: Direct3D sets FPU > to single precision mode) > http://groups.google.com/group/microsoft.public.win32.programmer.directx.managed/browse_frm/thread/10c3ba49a550edc4 > > Probably, somewhere in your code, maybe in a 3rd party component or if you > also use DirectX, the FPU is set to single-precision mode also. > > If i execute > > call TestAddition > Create Direct3D Device without FPU_Reserve flag > call TestAddition > > I get exactly the behavior you describe. > > > Armin > > Jeff Dillingham wrote:
> Armin: You're welcome! :)> > Wow! Dude! You are my new best friend. Yes, I use Direct3D in my > code. Never occurred to me that was related to the problem. I > followed the link you sent me. As advised I now set the FPUPreserve > flag when I create the Direct3D device. The problem went away > immediately. You have saved me days of headache and anxiety. Thanks > much. Armin
The process cannot access the file (in Windows2003 only)
Windows 7 dll import problem copying folders error when updating Listview after record add Can you edit auto generated Partial Class Designer VB code? unable to remove items from Listbox Controls not rendering Debugging a ClickOnce web-deployed app Radio buttond and combo boxes newbie setup question |
|||||||||||||||||||||||