Unfortunately, most decimal fractions cannot be represented exactly as binary fractions. A consequence is that, in general, the decimal floating-point numbers you enter are only approximated by the binary floating-point numbers actually stored in the machine.

This is a quote from the python article about this topic. You can google “floating point decimal issues” for more information.

Basically, you should be doing this:

local function trunc(x)
return math.floor(x * 10) / 10
end
if trunc(script.Parent.Parent.Head.Transparency) == 0.3 then
-- now you know that it's actually 0.3
end

oh I get it! your post makes sense. To add on, you can implement a round function by shifting your number over by 10, then flooring it, then shifting it back.

local function round(x)
return math.floor(x * 10) / 10
end

(This is more accurately a truncate function but for purpose we can just call it “rounding”)

Here’s another example of floating point decimal issues:

function randomOffset(vector, maxAngle)
local rand1 = random:NextNumber(0, tau)
local rand2 = random:NextNumber(math.cos(maxAngle / 1e3), 1)
local res = (CFrame.new(zeroVector, vector)
* CFrame.Angles(0, 0, rand1)
* CFrame.Angles(math.acos(rand2), 0, 0)
).LookVector
print(res:Dot(vector.Unit))
return res
end

When using this function, if you set maxAngle to 0, the resulting vector should be the same as the .Unit of the one originally provided. You can test this using result:Dot(originalVector.Unit), which is what I did in the function. If it’s the same vector, it should print 1, but it prints numbers like these instead: