Comparing numbers in Lua - lua

I'm checking for line-line intersection and need to figure out if the intersection point (x,y) is within the bounding box of a line segment l2 (consisting of points p1 and p2)
The following printout illustrates my problem:
the intersection point is (100,300)
print("x",x,">=",math.min(l2.p1.x,l2.p2.x),x >= math.min(l2.p1.x,l2.p2.x))
print("x",x,"<=",math.max(l2.p1.x,l2.p2.x),x <= math.max(l2.p1.x,l2.p2.x))
print("y",y,">=",math.min(l2.p1.y,l2.p2.y),y >= math.min(l2.p1.y,l2.p2.y))
print("y",y,"<=",math.max(l2.p1.y,l2.p2.y),y <= math.max(l2.p1.y,l2.p2.y))
which yeld:
x 100 >= 100 true
x 100 <= 100 false
y 300 >= 140 true
y 300 <= 300 false
What is going on and how can it be fixet?
(Lua version 5.2.3)

Say hello to float point arithmetic: http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
For example
> string.format("%.32f", 1/3)
0.33333333333333331482961625624739
> 1/3 == 0.3333333
false
So it depends on how your calculations of X and lp* looks like.
You should use a tolerance while comparing float point numbers.
> math.abs(1/3 - 0.33) == 0
false
> math.abs(1/3 - 0.33333) < 1/10^6
false
> math.abs(1/3 - 0.33333) < 1/10^5
true

Related

Rails rounding decimal to the nearest power of ten

I'm looking for a rails function that could return the number to the nearest power of ten(10,100,1000), and also need to support number between 0 and 1 (0.1, 0.01, 0.001):
round(9) = 10
round(19) = 10
round(79) = 100
round(812.12) = 1000
round(0.0321) = 0.01
round(0.0921) = 0.1
I've looking on : Round number down to nearest power of ten
the accepted answer using the length of the string, that can't applied to number between 0 and 1.
updated
Round up to nearest power of 10 this one seems great. But I still can't make it work in rails.
I'm not sure about any function which automatically rounds the number to the nearest power of ten. You can achieve it by running the following code:
def rounded_to_nearest_power_of_ten(value)
abs_value = value.abs
power_of_ten = Math.log10(abs_value)
upper_limit = power_of_ten.ceil
lower_limit = power_of_ten.floor
nearest_value = (10**upper_limit - abs_value).abs > (10**lower_limit - abs_value).abs ? 10**lower_limit : 10**upper_limit
value > 0 ? nearest_value : -1*nearest_value
end
Hope this helps.
Let's simplify your problem to the following form - let the input numbers be in the range [0.1, 1), how would rounding of such numbers look like then?
The answer would be simple - for numbers smaller than 0.5 we would return the number 0.1, for larger numbers it would be 1.0.
All we have to do is to make sure that our number will be in that range. We will "move" decimal separator and remember how many moves we made in second variable. This operation is called normalization.
def normalize(fraction)
exponent = 0
while fraction < (1.0/10.0)
fraction *= 10.0
exponent -= 1
end
while fraction >= 1.0
fraction /= 10.0
exponent += 1
end
[fraction, exponent]
end
Using above code you can represent any floating number as a pair of normalized fraction and exponent in base 10. To recreate original number we will move decimal point in opposite direction using formula
original = normalized * base^{exponent}
With data property normalized we can use it in our simple rounding method like that:
def round(number)
fraction, exponent = normalize(number)
if fraction < 0.5
0.1 * 10 ** exponent
else
1.0 * 10 ** exponent
end
end
if the number is >= 1.0, this should work.
10 ** (num.floor.to_s.size - ( num.floor.to_s[0].to_i > 4 ? 0 : 1))
Try this:
def round_tenth(a)
if a.to_f >= 1
return 10 ** (a.floor.to_s.size - ( a.floor.to_s[0].to_i > 4 ? 0 : 1))
end
#a = 0.0392
c = a.to_s[2..a.to_s.length]
b = 0
c.split('').each_with_index do |s, i|
if s.to_i != 0
b = i + 1
break
end
end
arr = Array.new(100, 0)
if c[b-1].to_i > 4
b -= 1
if b == 0
return 1
end
end
arr[b-1] = 1
return ("0." + arr.join()).to_f
end
class Numeric
def name
def helper x, y, z
num = self.abs
r = 1
while true
result = nil
if num.between?(x, y)
if num >= y/2.0
result = y.round(r+1)
else
result = x.round(r)
end
return self.negative? ? -result : result
end
x *= z; y *= z; r += 1
end
end
if self.abs < 1
helper 0.1, 1, 0.1
else
helper 1, 10, 10
end
end
end
Example
-0.049.name # => -0.01
12.name # => 10
and so on, you are welcome!

Geogebra plot range

I created this plot through the GeoGebra spreadsheet:
I would be interested in getting the same plot, but only in range between the first (1;3) and the last (3;4.5) point. How can I do this?
Thanks in advance
Ok this is my firs answer , you can type that in the input line below : If(1 < x < 3, f(x))
where f(x) is your function
For example, for f(x) = x^2, you can input like this: x² / (x < -1 ∨ x > 1)
(x < -1 ∨ x > 1) is a boolean value, True == 1, and False == 0. 0 as a denominator is meaningless, and this can be used to limit the display range in Geogebra.

A* only works in certain cases

My a* path finding algorithm only works for certain cases but I don't understand why. Every node in my grid is walkable so in theory every path should work. I believe the error is in this line:
PathFindingNode *neighbor = NULL;
if ((y > 0 && x > 0) && (y < gridY - 1 && x < gridX - 1))
neighbor = [[grid objectAtIndex:x + dx] objectAtIndex:y +dy];
In function -(void)addNeighbors:, the line
if ((y > 0 && x > 0) && (y < gridY - 1 && x < gridX - 1))
neighbor = [[grid objectAtIndex:x + dx] objectAtIndex:y +dy];
has bug because if curNode is on boundary, it does not add neighbors to the queue. So that the algorithm will never reach endNode in the four corners (i.e. [0,0], [gridX-1,0], [0,gridY-1], [gridX-1,gridY-1]).

Scaling a number between two values

If I am given a floating point number but do not know beforehand what range the number will be in, is it possible to scale that number in some meaningful way to be in another range? I am thinking of checking to see if the number is in the range 0<=x<=1 and if not scale it to that range and then scale it to my final range. This previous post provides some good information, but it assumes the range of the original number is known beforehand.
You can't scale a number in a range if you don't know the range.
Maybe what you're looking for is the modulo operator. Modulo is basically the remainder of division, the operator in most languages is is %.
0 % 5 == 0
1 % 5 == 1
2 % 5 == 2
3 % 5 == 3
4 % 5 == 4
5 % 5 == 0
6 % 5 == 1
7 % 5 == 2
...
Sure it is not possible. You can define range and ignore all extrinsic values. Or, you can collect statistics to find range in run time (i.e. via histogram analysis).
Is it really about image processing? There are lots of related problems in image segmentation field.
You want to scale a single random floating point number to be between 0 and 1, but you don't know the range of the number?
What should 99.001 be scaled to? If the range of the random number was [99, 100], then our scaled-number should be pretty close to 0. If the range of the random number was [0, 100], then our scaled-number should be pretty close to 1.
In the real world, you always have some sort of information about the range (either the range itself, or how wide it is). Without further info, the answer is "No, it can't be done."
I think the best you can do is something like this:
int scale(x) {
if (x < -1) return 1 / x - 2;
if (x > 1) return 2 - 1 / x;
return x;
}
This function is monotonic, and has a range of -2 to 2, but it's not strictly a scaling.
I am assuming that you have the result of some 2-dimensional measurements and want to display them in color or grayscale. For that, I would first want to find the maximum and minimum and then scale between these two values.
static double[][] scale(double[][] in, double outMin, double outMax) {
double inMin = Double.POSITIVE_INFINITY;
double inMax = Double.NEGATIVE_INFINITY;
for (double[] inRow : in) {
for (double d : inRow) {
if (d < inMin)
inMin = d;
if (d > inMax)
inMax = d;
}
}
double inRange = inMax - inMin;
double outRange = outMax - outMin;
double[][] out = new double[in.length][in[0].length];
for (double[] inRow : in) {
double[] outRow = new double[inRow.length];
for (int j = 0; j < inRow.length; j++) {
double normalized = (inRow[j] - inMin) / inRange; // 0 .. 1
outRow[j] = outMin + normalized * outRange;
}
}
return out;
}
This code is untested and just shows the general idea. It further assumes that all your input data is in a "reasonable" range, away from infinity and NaN.

Lua: Random: Percentage

I'm creating a game and currently have to deal with some math.randomness.
As I'm not that strong in Lua, how do you think
Can you make an algorithm that uses math.random with a given percentage?
I mean a function like this:
function randomChance( chance )
-- Magic happens here
-- Return either 0 or 1 based on the results of math.random
end
randomChance( 50 ) -- Like a 50-50 chance of "winning", should result in something like math.random( 1, 2 ) == 1 (?)
randomChance(20) -- 20% chance to result in a 1
randomChance(0) -- Result always is 0
However I have no clue how to go on, and I completely suck at algorithms
I hope you understood my bad explanation of what I'm trying to accomplish
With no arguments, the math.random function returns a number in the range [0,1).
Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Rio
> =math.random()
0.13153778814317
> =math.random()
0.75560532219503
So simply convert your "chance" to a number between 0 and 1: i.e.,
> function maybe(x) if math.random() < x then print("yes") else print("no") end end
> maybe(0.5)
yes
> maybe(0.5)
no
Or multiply the result of random by 100, to compare against an int in the range 0-100:
> function maybe(x) if 100 * math.random() < x then print(1) else print(0) end end
> maybe(50)
0
> maybe(10)
0
> maybe(99)
1
Yet another alternative is to pass the upper and lower limits to math.random:
> function maybe(x) if math.random(0,100) < x then print(1) else print(0) end end
> maybe(0)
0
> maybe(100)
1
I wouldn't mess around with floating-point numbers here; I'd use math.random with an integer argument and integer results. If you pick 100 numbers in the range 1 to 100 you should get the percentages you want:
function randomChange (percent) -- returns true a given percentage of calls
assert(percent >= 0 and percent <= 100) -- sanity check
return percent >= math.random(1, 100) -- 1 succeeds 1%, 50 succeeds 50%,
-- 100 always succeeds, 0 always fails
end

Resources