Tell me more ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

Here is a simple example:

Dim si As Single
For si = 2.6 To 3.3 Step 0.1
  MsgBox si
Next si

The numbers I get are as follows (they are shown below as they are displayed in the MsgBox):

2.6
2.7
2.8
2.9
3
3.099999
3.199999
3.299999

So, I figured I'd change the data type from Single to Double to see what happens. This time, there are no .099999 type numbers, but the last item (iteration) is skipped, as in, missing, and doesn't exist. Here are the results as they appear in the MsgBox display):

2.6
2.7
2.8
2.9
3
3.1
3.2

I'm guessing in the case of the missing last iteration, it keeps track of it like the .299999 and never reaches .3 in its own mind, so skips it? However, the problem with this is that if this were happening, you'd get one of the previous iteration appearing twice for this to be able to happen, as it did in the Single Data Type example, where, if you truncated everything after the first decimal, you'd notice 3.0 appeared twice. First as "3" and then as "3.0" (if we ignore/truncate the 5 occurrences of the digit 9 after the "3.0" part - "3.099999").

Interestingly, another function I have where I loop through something using the Single Data Type displays the exact problem that our Double Data Type example above has, and none of the problems our Single Data Type example above has. So, the real reason why I am here is my Single Data Type loop missing and skipping the last item when using "Step 0.1" (being incremented by 0.1).

Is there a reliable way to do this using a "Step 0.1" and non-integer data types? If not, do we know the rules by which these chaotic things occur (in that, is the chaos predictable)? sigh

I thought you would all find this interesting, and I sure am looking forward to understand it. Searching Google was useless since as soon as I entered the work "for" and "step" into it, kept bringing up samples on how to use the step operator and nothing useful.

I would be interested in knowing how to live with this, or do this safely, and/or why it is happening in the first place. I would rather not loop using Integers for this particular function (and then divide up using another variable to get my decimal types), however if I have to and there is no reliable way to do it otherwise, I will. But I leave this to you guys, my programmer overlords.

My examples were occurring in VB6, however, I'm also wondering if this same chaos is occurring in VB.NET and even in C#? I'm assuming it's occurring in vba and vbscript. Any info on this would also be interesting and appreciated.

Thank you in advance.

To the Moderators (not necessary reading for the question): This is not a duplicate post, there may be other people posting floating-point issues in other languages (such as C#) but the solution to this (VB6) question is not necessarily the same as the solution for the C# question. There may be some solutions that are the same, but there will be solutions that are different as well, and there would be no way for me to get the different solution/answers from the C# post. As it turned out, the solution that I was interested in was a VB6 specific solution that would not have been found on the C# post that was referenced. I urge the mods to be diligent before attempting to close posts, I have seen post closed unfairly on many occasions and at the end of the day, you get to a stage where you are not adding any value, but removing substantial value from the Q and A style of this website. In conclusion, if there is even the possibility that there is new information/answers or solutions to be had by a similar looking post, you are better off refraining from closing. Especially if the questions are for a different language, even if the concepts are similar or the same, there are bound to be different solutions and solutions that are language specific.

share|improve this question
2  
Possible duplicate of stackoverflow.com/search?q=floating+point+equal – GSerg Jul 6 '12 at 21:22
1  
Definite duplicate of stackoverflow.com/questions/11364996/… (From today) – Holger Brandt Jul 6 '12 at 21:24
This is one of those problems that trips a lot of new programmers. Here's a simple explanation with diagrams. ;-) – jac Jul 6 '12 at 21:27
1  
To keep a long story short, I recommend to read What Every Computer Scientist Should Know About Floating-Point Arithmetic – Steve Jul 6 '12 at 21:31
4  
@Erx_VB.NExT.Coder You might want to read faq in order to understand how this site works. The fact you are unfamiliar with the most basic principles of floating point arithmetics, which are language agnostic and apply to all languages including VB6, is not an excuse for the shouting you did above. Please read the links provided in the comments above and please don't think what you posted in a unique question about a unique problem noone else ever encountered. In fact, it is a duplicate of literally hundreds of exactly same questions. – GSerg Jul 6 '12 at 21:50
show 6 more comments

closed as not constructive by Doug Glancy, DJ., Jean-François Corbett, Jeremy Thompson, Evan Mulawski Jul 8 '12 at 1:38

As it currently stands, this question is not a good fit for our Q&A; format. We expect answers to be supported by facts, references, or specific expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, see the FAQ for guidance.

3 Answers

up vote 3 down vote accepted

Try using a decimal instead for precision:

For i As Decimal = 2.6 To 3.3 Step 0.1
  MessageBox.Show(i.ToString)
Next

If using VB6, you can try using the Currency type (as JeffSiver noted):

Dim i As Currency
For i = 2.6 To 3.3 Step 0.1
  MsgBox i
Next
share|improve this answer
we don't have decimals in vb6, but i think i can use a variant, even using a variant, the last item is missing. is this a problem with adding 0.1 to a single/decimal/double data type or is it only a problem when the For Loop does this using a non-integer Step operator? – Erx_VB.NExT.Coder Jul 6 '12 at 21:37
1  
In VB6, I'd use the currency datatype. This is a decimal datatype with a fixed four digits to the right of the decimal. I'm sure the problem is due to the nature of floating point numbers which. In VB.NET and c#, I'd use the decimal type as @LarsTech recommended. – Jeff Siver Jul 6 '12 at 21:41
@jeff siver but now I am worried that doing basic arithmatic on a single or non integer data type is going to have the same problem, or will it? like, adding 0.1 to 2.9 inside the for loop, but by using an integer to loop through things and dividing them by 10, will i have this problem? – Erx_VB.NExT.Coder Jul 6 '12 at 21:46
@jeff siver wow, i just used a currency data type for the above example, and everything worked. no .099999's and NO missing iteration, as in, the main problem i was having (the missing last iteration) is now solved. Do you have any idea on if this is reliable, why it was occuring, and can i expect it to work like this on clients machines? or is this bound by the rules of chaos as well? – Erx_VB.NExT.Coder Jul 6 '12 at 21:49
7  
@Erx_VB.NexT.Coder VB6 does have a Decimal data type. It has 14 bytes of precision. You are missing the point of all the answers and comments. Computers use a binary number system and your problem is just a rounding error. All programming languages have this issue. Using variables capable of greater precision decreases the problem, but does not eliminate it. You will need to change your code in some way because your iteration will not work in it's current form. If you want to fully understand the issue go to one of the links given in the comments, or to previous answers. – jac Jul 6 '12 at 21:53
show 3 more comments

I'd multiply by 10 and use integers for the loop. Even using decimal I think you could get in the same type of issue

share|improve this answer
ok, if i multiply by ten or use a do loop, will adding 0.1 to a single data type yield the same problem with the .099999's? Is this a problem with For Looping with a non integer Step or is this a simple problem with arithmetic (ie: i cant reliably add 0.1 to a single data type)...? – Erx_VB.NExT.Coder Jul 6 '12 at 21:35
the problem is the 0.1 not really being 0.1, so the for which is basically a loop with an addition and comparison at the end, fails. So, reduce it to integers (so if your numbers are 0.1, 0.2, etc, multiply by 10 and round them, and make the step = 1) – Rodolfo Jul 9 '12 at 14:29

The issue comes down to how floating point numbers are represented in memory. Which many others have posted links to good references on understanding how floating point numbers are represented.

When you tried using a double instead of a single the numbers incremented as follows -- had to step through with a debugger to get the values as ToString doesn't output the full precision of the value.

2.6
2.7
2.8000000000000003
2.9000000000000004
3.0000000000000004
3.1000000000000005
3.2000000000000006
3.3000000000000007

As you can see the final value was slightly more than the end of your for loop so it was skipped.

By using an integer instead you can avoid the floating point issue on your for loop, but you'll need to divide the number by 10 on each iteration to get the value you want to print.

Dim i As Integer
For i = 26 To 33 Step 1
        MsgBox(i / 10)
Next
share|improve this answer
+1 for a reasonable and correct answer – Cheers and hth. - Alf Dec 10 '12 at 3:20

Not the answer you're looking for? Browse other questions tagged or ask your own question.