# Impossible error occuring?

Hello,

I’ve ran into an issue that i’ve been debugging for the past hour with no success. A function that I’ve created, InverseLerp, is supposed to return a value [0, 1] depending on where Value is inbetween From and To.

This, however, is not the case. Instead, the function returns nil!? I’m unsure how this is possible as the function returns something in every case, even if all if statements fail.

# Use in script and proof that the arguments exist

local Alpha = InverseLerp(SmallestValue, LargestValue, HeightMap[X][Z])

# Function - InverseLerp

function InverseLerp(From :number, To :number, Value :number)
if From < To then
if Value < From then
return 0
end

if Value > To then
return 1
end

Value = Value - From
Value = Value/(To - From)
return Value
end

if From <= To then
return 0
end

if Value < To then
return 1
end

if Value > From then
return 0
end

return 1.0 - ((Value - To) / (From - To))
end

# The Issue

From all my tests, the function has a valid return UNLESS the From or To arguments are the same as the Value argument

This is probably a stupid caveat that I’ve overlooked but any help is appreciated!

1 Like

In my testing, I have failed to ever get a nil value.

function InverseLerp(From :number, To :number, Value :number)
if From < To then
if Value < From then
return 0
end

if Value > To then
return 1
end

Value = Value - From
Value = Value/(To - From)
return Value
end

if From <= To then
return 0
end

if Value < To then
return 1
end

if Value > From then
return 0
end

return 1.0 - ((Value - To) / (From - To))
end
print(InverseLerp(0.4991, 0.4991, 1.22323)) -- prints 0
print(InverseLerp(0.4991, 1.22323, 1.22323)) -- prints 1

Are you sure you aren’t making a mistake like printing the wrong value?

I’ve set the debugger print condition to be:

Alpha == nil

And the print to be:

"Alpha is nil", SmallestValue, HeightMap[X][Y], LargestValue

weird edge case, but you only defined the function once, right?

Is there a reason why you have to use if statements? It’s an algebraic equation you can just rearrange the variables

math equations have conditionals too

I’m confident that this error is just breakpoints being fired when they shouldn’t be.

I ran your code in a test loop with your breakpoint slightly modified.

for i = 0, 10 do
local small = math.random()
local large = math.random()
local value = math.random()

local a = InverseLerp(small, large, value)
end

Which provides this output:

I then modified my code as such

local a

for i = 0, 10 do
local small = math.random()
local large = math.random()
local value = math.random()

a = InverseLerp(small, large, value)
end

Which changed the output drastically to this

I then further changed my code and breakpoint

for i = 0, 10 do
local small = math.random()
local large = math.random()
local value = math.random()

local b = InverseLerp(small, large, value)
a = b
end

What conclusion do I draw from this? You’re running into this issue because your “alpha” value is initialized as nil, then set to a function call. However, it would seem that breakpoints fire as soon as their condition is met, even if the line they are attached to has not fully executed.

Is this intended? Maybe not. Is it weird? Yes. Is your code flawed with some really rare bug? Most definitely not.

1 Like

No they don’t. If his whole thing was sometimes it wouldn’t be exactly 0 or 1 then he could do this

local function inverseLerp(from, to, value)
local tolerance = 0.000001
local step = (-from+value)/(-from+to)
if step < tolerance then
step = 0
elseif 1-step < tolerance then
step = 1
end
return step
end

Here is the section of the code:

-- ...

local function InverseLerp(From, To, Value)
if From < To then
if Value < From then
return 0
end

if Value > To then
return 1
end

Value = Value - From
Value = Value/(To - From)
return Value
end

if From <= To then
return 0
end

if Value < To then
return 1
end

if Value > From then
return 0
end

return 1.0 - ((Value - To) / (From - To))
end

-- ...

local MaterialMap = {}

-- ...

local Materials = {
{Height = .90, Material = Enum.Material.Snow},
{Height = .80, Material = Enum.Material.Rock},
{Height = .50, Material = Enum.Material.Grass},
{Height = .30, Material = Enum.Material.Sand},
{Height = .10, Material = Enum.Material.Water}
}

-- ...

for X = 1, SizeX do -- SizeX is usually 200
MaterialMap[X] = {}

for Z = 1, SizeZ do -- SizeZ is usually 200
local Alpha = InverseLerp(SmallestValue, LargestValue, HeightMap[X][Z]) -- Breakpoint prints nil if Value equal to From or To
print(Alpha) -- also prints nil if Value equal to From or To
-- Values that are not exactly equal to From or To usually return correctly (not nil)

local Material = nil

for _, Level in ipairs(Materials) do
if Alpha > Level.Height then
MaterialMap[X][Z] = Level.Material
Material = Level.Material
break
end
end
end
end

for X = 1, SizeX do
for Z = 1, SizeZ do
local Material = MaterialMap[X][Z]
local Y = HeightMap[X][Z]

local Position = Vector3.new(X - (SizeX / 2), Y + (math.abs(SmallestValue) * 100), Z - (SizeZ / 2))
local Orientation = CFrame.Angles(0, 0, 0)
local Size = Vector3.new(1, 1, 1)

local CoordinateFrame = CFrame.new(Position) * Orientation

Terrain:FillBlock(CoordinateFrame, Size, Material) -- Error: Argument 3 missing or nil
end
end

I don’t think you’re setting every value in the MaterialMap because you’re only setting it if Alpha is > a Height from Materials, but ignoring the case where Alpha is 0.10 or lower

I’d output MaterialMap after the first outer loop

You are correct, I forgot to check if the value was bigger than or equal to the level’s height.