If Statement Inside Of While Loop Won't Work

I’ve been doing some tests with different kinds of loops and using if statements, and I can’t seem to make this one script work. It’s quite simple - I’m trying to make it print “3 Has Been Reached” when the while loop makes my variable (StartNum) equal 3. It counts up in increments of 0.1 seconds as I want it to, but when it reaches 3 it just stops in the output, there’s no “3 Has Been Reached”.

I’ve also tried doing the while loop, then after it stops do the if statement - but it still didn’t work. I feel like I’m doing something wrong that’s obvious. :sweat_smile: Thanks for any help.

Here’s the script:

local function StartEnd()
	local StartNum = 0
	
	while StartNum < 3
	do
		StartNum = StartNum + 0.1
		if StartNum == 3 then
			print("3 Has Been Reached!")
		else
			wait(0.1)
			print(StartNum)
		end
	end
end

StartEnd()
1 Like

“3 Has Been Reached!” won’t print because of this

as it’ll only keep running if it’s lesser than 3 and so the second comparison will never be made.

local function count(n)

local floor = math.floor -- due to floating point issues

for n = 0, n, 0.1 do
    if floor(n) == 3 then print("reached 3!") 
	else
		print(n)
	end
    	wait(0.1)
    end
end

count(3.1) --> will give desired output

 -- another thing you could do

local var = 0

while true do 
      var += 0.1
      if var >= 3 then print "reached 3" break end
      print(var)
	  wait(0.1)
   end

Edit: Now that I’ve got more time to explain:

While ‘loops’ essentially rely on one condition to return true after every iteration to keep running further iterations, every iteration the condition is evaluated and if it returns false, the code within the block won’t run the current iteration.

My proposition here was that “it’ll only keep running if it’s lesser than 3” and that is correct in my context since each iteration will run successfully if whatever the variable holds is lesser than 3 by the time the evaluation can be made.

Within the iteration your code increments the number to something greater than 3 thus the next iteration is skipped entirely and the comparison if x == y somewhere further within the block isn’t evaluated at all.

Sorry for any confusion due to lack of detailed explanation earlier.

cc @wow13524 , @MJTFreeTime

4 Likes

Since you did while StartNum < 3 do, the code only repeats while it’s under 3. Basically, it’s implied that StartNum has reached 3 at the end of your while loop

Here’s something I did:

local StartNum = 0

while StartNum < 3 do
	StartNum += 0.1
	print(StartNum)
	
	wait(0.1)
end

print("StartNum has reached 3 ("..StartNum..")")

It worked for me:
Screen Shot 2020-06-27 at 11.36.04 PM

1 Like

Question, why does it never print “3 Has Been Reached” even if the loop continues to a higher number?

local function StartEnd()
	local StartNum = 0
	
	while StartNum < 4
	do
		StartNum = StartNum + 0.1
		if StartNum == 3 then
			print("3 Has Been Reached!")
		else
			wait(0.1)
			print(StartNum)
		end
	end
end

StartEnd()
1 Like

.1 can’t be represented perfectly in binary form, the same way 1/3 can’t be represented perfectly in base-10 or decimal form, as it spits out .33333333. We have limited amount of paper, so we round .333333 at some point, making it ultimately inaccurate.
So for example, we can add .333333 (rounded to the third decimal)
.333 + .333 + .333 = .999, not 1. This is because of rounding, and is referred to as a rounding error.

To fix it, never assume that numbers with decimal places will be exact. Use
if StartNum >= 3 then

Just for the sake of learning, the numbers that do compute well are binary fractions or inverse powers of two, same as an american tape measure scale. halves, quarters, eighths, sixteenths, etc. 7/16 is fair game, 2/17 is not.

4 Likes

Both @XxELECTROFUSIONxX and @OIogist aren’t quite correct with their reasoning: Assuming you were incrementing the counter by 1 rather than .1, the condition (if startNum < 3) is checked BEFORE the body is ran; if the condition evaluates to false, then the do-end block is skipped entirely.
If startNum == 2 when the condition is checked, it will evaluate to true, since 2 < 3. Cool. Now, the important part is how you’re incrementing startNum AFTER the condition check, meaning that startNum CAN EQUAL 3 inside the body (This is pretty much a for loop, but with the potential to have a variable increment; yours would look like for _=0,3,.1 do).
In this case, I would discard such reasoning and instead listen to @JarodOfOrbiter. Lua numbers are represented as 64-bit floats, and that will eventually introduce inconsistencies somewhere when you’re attempting to increment startNum by a decimal number. You could solve this by incrementing by a whole number OR changing your if statement to check if startNum is GREATER THAN OR EQUAL TO 3.

1 Like

I’m sure multiple of your guys’ fixes would’ve worked, but I just found yours to be more of what I was looking for. I appreciate all the suggestions and info. Thanks everyone! :grin:

1 Like

Assuming you did in fact not just skim over my reply and read through it entirely,

math.floor returns an integer, this can be used to prevent most cases involving issues due to floating point numbers’ accuracy by having a target value of 0.1 + your original end value, that’ll mean your greatest number while incrementing can only possibly be 3 or greater than 3 and floor that then because you can’t guarantee it’ll be exactly the newer value too due to again the inconsistencies while incrementing a decimal number and comparing it with an exact value - you could on the other hand just compare it using the >= operator instead instead of substantially rounding the value to the largest integer smaller or equal to it.

@MJTFreeTime
I did edit my post to include the other way, have a look that too if you want.

1 Like