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. 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()
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.
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..")")
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 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.
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.
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!
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.