How to get the finest possible precision in JavaScript? - javascript

I'm trying to determine the smallest possible non-negative, non-zero value available in a JavaScript number for addition and subtraction. If necessary then the smallest possible number for addition and subtraction per a given value (i.e. if the "smallest value" differs between numbers at a given range I'd like to find the smallest value for a given number or range of numbers, or the next number greater or smaller than a given number would also work.)
As an example to underline why I'm looking for this, please see this fiddle or the code below. It simply scales a rectangle by area, given both the starting width/height and ending width/height the values should be in whole numbers. It works as outlined below for the given example however I'm fairly sure the fudge-factor of 0.000000000000002 won't scale to any possible set of values. I understand the overwhelming majority of solutions in the floating point range of possible values will not be whole numbers and that many will likely even extend beyond the JavaScript number's level of precision or simply be unable to be represented in it, however given the check below for greater than or less than based on ration and/or area I have a high degree of confidence that if I can find the smallest possible value which the result can be offset I can at least hit the number most computationally accurate for a given input, which would be the objective here.
console.clear();
var w = 3;
var h = 5;
var a = w * h;
var r = w / h;
console.log(w, h, a, r);
var t = 240;
var w2 = Math.sqrt(t);
var h2 = w2;
w2 = w2 * r / Math.sqrt(r);
h2 = h2 / r * Math.sqrt(r);
var r2 = w2 / h2;
var m = 10;
var a2 = w2 * h2;
console.log(w2, h2, a2, r2);
while ((r2 > r) && (m > 0)) {
h2 += 0.000000000000002;
r2 = w2 / h2;
m--;
}
m = 10;
while ((r2 < r) && (m > 0)) {
h2 -= 0.000000000000002;
r2 = w2 / h2;
m--;
}
var a2 = w2 * h2;
console.log(w2, h2, a2, r2);
Output:
Console was cleared
3 5 15 0.6
12 20.000000000000004 240.00000000000006 0.5999999999999999
12 20 240 0.6

The smallest possible number can be interpreted in several ways. For the sake of usefulness to others I will post information about all three interpretations, although I believe you are looking for the first one:
If you mean in terms of precision - the smallest possible number closest to zero:
Number.MIN_VALUE
would give you: 5e-324
If instead you mean the smallest possible floating point number, which would include negative numbers, then you'd be looking for:
- Number.MAX_VALUE
Note the minus sign there. That would give you: -1.7976931348623157e+308.
And the third interpretation is the difference between 1 and the smallest floating point number greater than 1, also known as the Machine Epsilon, in which case you can use:
Number.EPSILON
Which would give you: -2.220446049250313e-16.
As a final note, the examples may be inaccurate if you are running on a CPU that supports different floating point storage scheme, like a 32bit CPU for example.

Related

How to determine the number that when multiplied will get you the closest to a target number?

Let's say I have the number 2062 and the multiplier is 0.75
What is the JavaScript formula to find which number that, when multiplied by 0.75, will come the closest to 2062?
PS: The closest here means either equal (==) or very close, but below the target number, and not very close but above.
You are looking for x in x * 0.75 = 2062. So solving for x that should be x = 2062 / 0.75. To ensure that the number is the closest whole number less than or equal to x, you can use Math.floor:
Math.floor(2062 / 0.75) = 2749
function findFactor(a, b) {
return Math.floor(a / parseFloat(b));
}
findFactor(2062, 0.75) -> 2749
https://jsfiddle.net/0s8cr5gd/

javascript typeof / NaN confusion

So I'm making a small game using the canvas API and and I'm fairly new to Javascript. But while I was working on making the charecter be able to shoot in a full 360 degrees I came across a error in the code below (this function should return the angle between the mouse position and player position nothing else)
calculateAngle : function(x,y){
var opp = 0; //opposite
var adj = 0; //adjecent
var rad = 0; //radian
var ang = 0; //angle
//side lengths
var x1 = gfx.player_center_x //the player x position
var x2 = mouse_x; //the mouse x position
var y1 = gfx.player_center_y; //the player y position
var y2 = mouse_y; //the mouse y position
//find 2 lengths of the triangle
opp = (y2 - y1);
adj = (x2 - x1);
//find the missing angle between the adjecent and hypotenuse
rad = Math.atan2(adj, opp);
ang = rad * 180 / Math.PI;
//-------------------------//
console.log(ang); //prints: NaN
console.log(typeof ang); //prints: number
//------------------------//
return ang;
}
When executed its returns NaN but ang is a number!
Why does javascript think the variable ang not a number? Its declared as 0 which typeof returns number, please help!
UPDATE: Careless error made, x1 and y1 ect changed location and I forgot to implement it, thanks for you answers though
NaN is a special value. Internally it's a number, but it's a specific value that's given the special meaning of "this value is mathematically undefined". Any operation that results in an undefined number (such as 0/0) results in NaN, but it's still a number! Just not a defined number.
Math.atan2 is implemented in such a way that it cannot return NaN (because it handles the "edge cases" where y/x would be Infinity - another "number" that isn't a defined number) so it seems almost certain that your NaN is coming from the calculation of opp and/or adj. You should log these values and see what's up.
NaN is a IEEE 754 “Not-a-Number” value. In javascript it belongs to the number type even it is known as NaN(Not a Number). It's a quirks of javascript. Even according to
IEEE Standard for Floating-Point Arithmetic (IEEE 754):
arithmetic formats: sets of binary and decimal floating-point data, which consist of finite numbers (including signed zeros and subnormal numbers), infinities, and special "not a number" values (NaNs).

KinectJS: Algorithm required to determine new X,Y coords after image resize

BACKGROUND:
The app allows users to upload a photo of themselves and then place a pair of glasses over their face to see what it looks like. For the most part, it is working fine. After the user selects the location of the 2 pupils, I auto zoom the image based on the ratio between the distance of the pupils and then already known distance between the center points of the glasses. All is working fine there, but now I need to automatically place the glasses image over the eyes.
I am using KinectJS, but the problem is not with regards to that library or javascript.. it is more of an algorithm requirement
WHAT I HAVE TO WORK WITH:
Distance between pupils (eyes)
Distance between pupils (glasses)
Glasses width
Glasses height
Zoom ratio
SOME CODE:
//.. code before here just zooms the image, etc..
//problem is here (this is wrong, but I need to know what is the right way to calculate this)
var newLeftEyeX = self.leftEyePosition.x * ratio;
var newLeftEyeY = self.leftEyePosition.y * ratio;
//create a blue dot for testing (remove later)
var newEyePosition = new Kinetic.Circle({
radius: 3,
fill: "blue",
stroke: "blue",
strokeWidth: 0,
x: newLeftEyeX,
y: newLeftEyeY
});
self.pointsLayer.add(newEyePosition);
var glassesWidth = glassesImage.getWidth();
var glassesHeight = glassesImage.getHeight();
// this code below works perfect, as I can see the glasses center over the blue dot created above
newGlassesPosition.x = newLeftEyeX - (glassesWidth / 4);
newGlassesPosition.y = newLeftEyeY - (glassesHeight / 2);
NEEDED
A math genius to give me the algorithm to determine where the new left eye position should be AFTER the image has been resized
UPDATE
After researching this for the past 6 hours or so, I think I need to do some sort of "translate transform", but the examples I see only allow setting this by x and y amounts.. whereas I will only know the scale of the underlying image. Here's the example I found (which cannot help me):
http://tutorials.jenkov.com/html5-canvas/transformation.html
and here is something which looks interesting, but it is for Silverlight:
Get element position after transform
Is there perhaps some way to do the same in Html5 and/or KinectJS? Or perhaps I am going down the wrong road here... any ideas people?
UPDATE 2
I tried this:
// if zoomFactor > 1, then picture got bigger, so...
if (zoomFactor > 1) {
// if x = 10 (for example) and if zoomFactor = 2, that means new x should be 5
// current x / zoomFactor => 10 / 2 = 5
newLeftEyeX = self.leftEyePosition.x / zoomFactor;
// same for y
newLeftEyeY = self.leftEyePosition.y / zoomFactor;
}
else {
// else picture got smaller, so...
// if x = 10 (for example) and if zoomFactor = 0.5, that means new x should be 20
// current x * (1 / zoomFactor) => 10 * (1 / 0.5) = 10 * 2 = 20
newLeftEyeX = self.leftEyePosition.x * (1 / zoomFactor);
// same for y
newLeftEyeY = self.leftEyePosition.y * (1 / zoomFactor);
}
that didn't work, so then I tried an implementation of Rody Oldenhuis' suggestion (thanks Rody):
var xFromCenter = self.leftEyePosition.x - self.xCenter;
var yFromCenter = self.leftEyePosition.y - self.yCenter;
var angle = Math.atan2(yFromCenter, xFromCenter);
var length = Math.hypotenuse(xFromCenter, yFromCenter);
var xNew = zoomFactor * length * Math.cos(angle);
var yNew = zoomFactor * length * Math.sin(angle);
newLeftEyeX = xNew + self.xCenter;
newLeftEyeY = yNew + self.yCenter;
However, that is still not working as expected. So, I am not sure what the issue is currently. If anyone has worked with KinectJS before and has an idea of what the issue may be, please let me know.
UPDATE 3
I checked Rody's calculations on paper and they seem fine, so there is obviously something else here messing things up.. I got the coordinates of the left pupil at zoom factors 1 and 2. With those coordinates, maybe someone can figure out what the issue is:
Zoom Factor 1: x = 239, y = 209
Zoom Factor 2: x = 201, y = 133
OK, since it's an algorithmic question, I'm going to keep this generic and only write pseudo code.
I f I understand you correctly, What you want is the following:
Transform all coordinates such that the origin of your coordinate system is at the zoom center (usually, central pixel)
Compute the angle a line drawn from this new origin to a point of interest makes with the positive x-axis. Compute also the length of this line.
The new x and y coordinates after zooming are defined by elongating this line, such that the new line is the zoom factor times the length of the original line.
Transform the newly found x and y coordinates back to a coordinate system that makes sense to the computer (e.g., top left pixel = 0,0)
Repeat for all points of interest.
In pseudo-code (with formulas):
x_center = image_width/2
y_center = image_height/2
x_from_zoom_center = x_from_topleft - x_center
y_from_zoom_center = y_from_topleft - y_center
angle = atan2(y_from_zoom_center, x_from_zoom_center)
length = hypot(x_from_zoom_center, y_from_zoom_center)
x_new = zoom_factor * length * cos(angle)
y_new = zoom_factor * length * sin(angle)
x_new_topleft = x_new + x_center
y_new_topleft = y_new + y_center
Note that this assumes the number of pixels used for length and width stays the same after zooming. Note also that some rounding should take place (keep everything double precision, and only round to int after all calculations)
In the code above, atan2 is the four-quadrant arctangent, available in most programming languages, and hypot is simply sqrt(x*x + y*y), but then computed more carefully (e.g., to avoid overflow etc.), also available in most programing languages.
Is this indeed what you were after?

Grid view height/width formula

I have an rectangle area that I want to fit a varing amount of sqaure items. Here is an image to help with the problem.
Could anyone help me with a formular to calculate the width/height(Bw/Bh) of the items?
I tried √(WxH/N).
But with an example of W = 1400, H = 380, N = 16 that gave me 182. But 1400/182 only gives 7.7 boxes width and 2.08 high (Multiplied I get my 16, but I need them to fit within the area).
Any ideas?
EDIT:
Getting closer I think what I really need to know is based around the aspect ratio and how to work out a grid that accommodate the items. E.g. 16 boxes below in 254 x 133 is 6 by 3.
EDIT:
I've now wrote the following code to work out the grid (javascript). Problem is that it is using a trail and error method.
var W = 254,
H = 133,
N = 16,
Bh = H;
while( ((Math.floor(W/Bh)) * (Math.floor(H/Bh))) < N ){
Bh--;
}
alert('Columns: '+Math.floor(W/Bh)+', Rows: '+Math.floor(H/Bh)+', Bow width: '+(Bh) );
See http://jsfiddle.net/GVp4X/ to test the code. I'm still certain there is a better way though.
You should define some meaningful constraint for the aspect ratio of the (small) boxes. For example, you can always divide the big box into N parts vertically or horizontally, but I don't think that is what you want to do. And for prime numbers N, this is the only thing you can do. Would it be okay to add "padding" of empty boxes in this case?
EDIT:
If N is reasonably small, you can just loop through all possible, w, the numbers of boxes per row and minimize some suitable penalty function for wrong aspect ratio and number of unused boxes. Here's an example (in Matlab code)
N = 123;
target_aspect = 4/3;
W = 80;
H = 60;
min_F = inf;
for w=1:N,
h = ceil(N/w);
Bh = H/h;
Bw = W/w;
padding = h*w-N;
aspect = Bw / Bh;
%# The penalty function to minimize
F = abs(aspect-target_aspect) + padding * 0.05;
if F < min_F,
min_F = F;
best_w = w;
end
end
EDIT2:
It is also possible to do this with a fixed aspect ratio if empty space ("ypadding") is allowed, for example, at the bottom margin. Then the loop body could be something like
Bw = W/w;
Bh = Bw/aspect;
h = floor(H/Bh);
n = w*h;
if n >= N,
ypadding = H-Bh*h;
padding = h*w-N;
%# penalty function
F = (ypadding/Bh)*0.3 + (padding / w)*0.2
if F < min_F,
min_F = F;
best_w = w;
end
end
In this case the search range for w can also be reduced by solving a quadratic problem.

Javascript function for trilinear interpolation

All,
I THINK that I'm looking for a function for Trilinear interpolation.
Here's the details:
I have a three dimensional dataset:
Dimension 1 varies from 0 to 100 in increments of 5
Dimension 2 varies from 0 to 100 in increments of 5
Dimension 3 varies from 0 to 1 in increments of 0.1
So, I have 4851 total values (21 x 21 x 11).
If I need to find the value for (10, 25, 0.3) - that's easy - I can just look it up in the 3-dimensional array.
But, I need to be able to come up with the best approximation, given dimensional values of (17,48,0.73), for example.
So, I think that what I'm looking for is a trilinear interpolation (although I'd definitely appreciate any suggestions for a better method, or a hint that I'm on the wrong topic altogether...)
A quick google search turns up this formula:
Vxyz =
V000(1-x)(1-y)(1-z) +
V100x(1-y)(1-z) +
V010(1-x)y(1-z) +
V001(1-x)(1-y)z +
V101x(1-y)z +
V011(1-x)yz +
V110xy(1-z) +
V111xyz
Which looks like what I'm looking for, but I'm not sure what x, y, and z represent. If I had to guess, x is a ratio - the distance of my "target" first dimension value from the nearest two values I have, y is the ratio for the second dimension, and z is the ratio for the third dimension.
Of course, since I don't really know what I'm talking about, I wouldn't know if this is right or wrong.
So, ideally, I'd like a bit of Javascript or pseudo-code that shows exactly how to accomplish this.
Many thanks in advance!
The code you are looking at is trying to do a weighted average of the 8 points of the cube with vertices that are in your dataset, and which encloses the point you are trying to find a value for.
For a point p
// Find the x, y and z values of the
// 8 vertices of the cube that surrounds the point
x0 = Math.floor(p.x / 5);
x1 = Math.floor(p.x / 5) + 1;
y0 = Math.floor(p.y / 5);
y1 = Math.floor(p.y / 5) + 1;
z0 = Math.floor(p.z / .1);
z1 = Math.floor(p.z / .1) + 1;
// Look up the values of the 8 points surrounding the cube
p000 = dataset[x0][y0][z0];
p001 = dataset[x0][y0][z1];
// ...
// Find the weights for each dimension
x = (x - x0) / 5;
y = (y - y0) / 5;
z = (z - z0) / .1;
// Compute the guess using the method you found
// ...

Categories

Resources