bri189a Posted October 4, 2005 Posted October 4, 2005 I get the following bug and use the below work around: Have 4 text boxes with the following numbers, I have to keep numbers and total at the 100th's precision, so these are valid inputs: 99.69, 0.05, 0.21, 0.05 Total the four in a loop as so: (Pseudo code - important part is just the loop) Dim total as Double For i as Integer = 0 to Me.txtBoxesCollection.Count - 1 total += Convert.ToDouble(Me.txtBoxesCollection(i).Text) Next i I end up with 99.999999987 or something weird like that - don't know why. I get this. If I change my code to force the round it works fine - problem is that the 0.21 when added to the total acts more like 0.2000000009???? It's weird Work around: total = Math.Round(total + Convert.ToDouble(Me.txtBoxesCollection(i).Text, 2) None of my numbers are outside of the 100ths place so I don't understand why I would need to round to the 100ths place - a calculator doesn't result in any numbers going beyond the 100ths place when doing this calculation... Does anyone know what could be causing this? Quote
*Experts* Volte Posted October 5, 2005 *Experts* Posted October 5, 2005 Internal floating point math is not entirely precise like that, so you will probably need to round off some numbers to get the desired result. Quote
Leaders snarfblam Posted October 5, 2005 Leaders Posted October 5, 2005 This is not a bug specific to .Net, either. This is floating point math with computers, period. You will sometimes find your results off by one or two in the least signifigant digit. Sometimes it makes your numbers look ugly (69.99999999 instead of 70) but in mathematical terms the roundoff error isn't particularly signifigant. You might find that your results will be better if you use the Decimal data type (and you might not). You might also want to use one of the Double.ToString to format your number to round off so something close will appear correctly (99.99999 will round to 100.00). Quote [sIGPIC]e[/sIGPIC]
bri189a Posted October 5, 2005 Author Posted October 5, 2005 Okay, but I don't understand why it will take 96.74 and add 0.21 and get 98.94999999991 - that may not be exactly what I have above, but it's the point - in the watch window I have those two numbers - so how does this happen? It seems to me having to round the result of 0.07 + 0.81 to decimal places is just a waste of code and gives the 'appearance' of a coder who doesn't know what he's doing in reality he's just trying to get past this 'floating-point' math problem. Quote
Nate Bross Posted October 5, 2005 Posted October 5, 2005 Your avatar sums it up nicely bri189a... Quote ~Nate� ___________________________________________ Please use the [vb]/[cs] tags on posted code. Please post solutions you find somewhere else. Follow me on Twitter here.
sgt_pinky Posted October 5, 2005 Posted October 5, 2005 Well, thats just the nature of using a digital computer to solve mathematical problems, doesnt matter how long the mantissa is, it's just the fact that its finite. The reason that you get the correct answer on a calculator, but not if you do 64 bit floating point precision mathematics in a computer (Type Double in VB.NET), is actually due to the LACK of precision in the calculator, not BETTER precision in the calculator. Quote
*Experts* Nerseus Posted October 5, 2005 *Experts* Posted October 5, 2005 Have you tried the decimal datatype? I did a quick test in C# Express Beta (a bit older - early summer), which uses .NET 2.0 beta, and could not repro your results. I used your values stored as strings with Convert.ToDouble(), added the results the same as you into a new double variable. In everything I tried, I got back 100.0. I tried with decimal and double. The only real difference is that I didn't use a textbox array, but used strings instead. I can post my code tomorrow if it helps. In any case, I've seen "rounding" issues with double values and can't remember offhand if double was better, or decimal. I think decimal was better suited to these "currency" related issues than double, but I may have that reversed. Maybe try going back to VB6 which had a Currency type :) -nerseus Quote "I want to stand as close to the edge as I can without going over. Out on the edge you see all the kinds of things you can't see from the center." - Kurt Vonnegut
Wile Posted October 5, 2005 Posted October 5, 2005 This is not a bug specific to .Net' date=' either. This is floating point math with computers, period. You will sometimes find your results off by one or two in the least signifigant digit. Sometimes it makes your numbers look ugly (69.99999999 instead of 70) but in mathematical terms the roundoff error isn't particularly signifigant.[/quote'] I thought it was even worse than just being inaccurate, the amount of inaccuracy was dependent on the CPU used (not just brand amd/intel, but actual model as well). I always believed the floating point bug that was in the early versions of the original Pentium was related to this where the inaccuracy was large enough to become significant. This inaccuracy is also why you should never directly compare 2 floats. For instance: dim fl1 as float = 4 dim fl2 as float = 16 if (fl1 * 2) = (fl2 / 2) then MessageBox.Show("They are equal") end if 4 x 2 = 8 and 16 / 2 = 8, so that messagebox should be shown if floats behaved. However I give you a 75% change you wont get that messagebox as floats are to inaccurate to use absolute precision. (hope the code makes sense, my vb is a bit rusty ;) ) If you are always working on 2 digits you can use another workaround. Instead of working with floats and trying to get rid of the inaccuracy, you can internally use an int/long and divide it by 100 when it needs to be displayed / multiply it by 100 when read from the user interface. This would require some work if you have an extensive algorithm, but it would get rid of the inaccuracy. Quote Nothing is as illusive as 'the last bug'.
samsmithnz Posted October 5, 2005 Posted October 5, 2005 I noticed this problem a while ago too. It was happening for very simple calculations. I worked around it by rounding or using the decimal data type. It is frustrating though, I must admit, as it's a hard bug to test for. Quote Thanks Sam http://www.samsmith.co.nz
bri189a Posted October 5, 2005 Author Posted October 5, 2005 Thanks everyone - at least now I know it's not me and I'm not going crazy! :) Quote
penfold69 Posted October 6, 2005 Posted October 6, 2005 As a brief background, it is because all numbers are stored in binary form. With integers, its not actually a problem, but when you start getting to decimals, representing them in binary becomes more and more difficult. A highly simplified example would be something like: 7.5 = 0111.1 (working in binary, the .1 = (1 * 2 ^ -1) = (1 / 2) = 0.5) So basically, as you move to the right after the decimal point, the digits represent: 1/2, 1/4, 1/8, 1/16 etc. etc. So, to create any decimal, you need it to be represented as a combination of fractions. The more binary significant digits that you use, the more accurate your answer will be, but for some numbers, it will NEVER be exact. Although the computer will actually approximate the correct answer in most cases, when you come to add/subtract/multiply or divide then this is where inconsistencies are likely to appear. See, I knew my college Comp Sci course (where I spent four weeks working with binary on paper.. ugh!) had a use! B. Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.