Hey i'm comparing 2 Vector.y's but it isnt working!
Here the code:
print(last.y + " == " + controller.transform.position.y);
if (last.y == controller.transform.position.y)
The print: 0,7999999 == 0,7999999
You are comparing floating point numbers. To get those exactly equal is hard. Unity only shows a limited amount of decimals in the editor. Try rounding the numbers.
https://docs.unity3d.com/ScriptReference/Mathf.Round.html
I.e.:
float randomNumber = 2.543686;
randomNumber = Mathf.Round(randomNumber * 100.0) / 100.0;
will return 2.54
Depending on how precise you want you could also do:
// If absolute difference between last y and controller pos y is less than 0.0001
if (Mathf.abs(last.y - controller.transformer.position.y) < 0.0001f) {
// do something
}
Related
I have this for loop:
for (double x = -1 * (display.Width / zoom); x <= (display.Width / zoom); x += 0.1)
{
//..
}
x is initialized to -20 and is compared against 20. Ideally, I would like x to be incremented as -20, -19.9, -19.8, etc. In practice, this is not what happens; on some iterations, there is indeed only one digit after the decimal point, but in others, it is not as precise, for example -19.8999999. This is responsible for some very irritating (and hard to find) bugs in my program.
How can I make it so that x stays 'relatively round'?
Don't use double or float if you need this kind of accuracy - use decimal instead.
This is happening because certain fractions cannot be accurately represented in binary - I suggest reading What Every Computer Scientist Should Know About Floating-Point Arithmetic.
This has to do with the way a double is stored. Try a decimal instead.
Use integer loop counter, initialized to -200 and compared against 200, and calculate your real x in each iteration.
UPD: using Decimal is probably better.
If i understand you right... why you just round it?
Math.Round(x,1)
Floating point numbers (Double/Float) aren't accurate, instead use -200 and 200 as an int. That will allow to not have to worry about lack of floating point precision.
For more information about this imprecision, I suggest this document.
http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
IF you really want it as precise as possible scale it up so that you can work with int or long... for example:
long _Z = (long) ((display.Width * 10) / zoom);
for (long _x = -1 * _Z; _x <= _Z; _x += 1)
{
double x = ((double)_x) / 10.0;
// ...
}
if you must use double you could use like this:
double x = 0.0;
while (x <= 3.0)
{
//Do your stuff
x = Math.Round(x + 0.1, 1);
}
I am trying to find the closest point on a parabola to an arbitrary point in 2d, for a DirectX pixel shader.
A great amount of googling has revealed to me that this is a common pre-calculus homework problem. Unfortunately, the hundreds of relevant answers all say things like "Once you have this equation, use your graphing calculator's minimum function and it will tell you the answer is 6."
I confess that I recall nothing of pre-calculus. I recognize that the equation I seek is probably sitting right there on wikipedia, but I can't figure out how to convert these greek symbols into an HLSL function. A solution in C, C++, C#, or any other language would also be greatly appreciated.
edit: Per a request to see the format of the input curve:
//Equation of parabola being y = ax^2 + bx + c
//p is the arbitrary point we're trying to find the closest point on the parabola for.
float2 GetClosestPointOnParabola(float a, float b, float c, float2 p)
{
//Something involving the distance formula...
//Something involving "minimization"...
return float2(x, y);
}
You could make use of this:
Pmin = (xmin, ymin) ~ point on a parabola
P = (px, py) ~ point in 2d
y = a*x^2 + bx + c ~ parabola
P(x) = (x-px)^2 + (y-py)^2 = (x-px)^2 + (a*x^2 + bx + c - py)^2
You need to calculate the P(x) derivative, it's not that difficult. E.g.
If you get: P(x) = x^4 + 4x^2 - 3x + 10 the derivative would be:
P'(x) = 4x^3 + 8x - 3
I think you get how to calculate that. Then compare P'(x) to zero to find where it crossess an X-axis. You find an xmin from that and then you have ymin from:
y = a*x^2 + bx + c
That's it.
I assume what you want is the point on a parabola that is closest to another point in the plane. Let's assume the parabola is given by y = a * x^2 + b * x + c and that you want to find the point on it closest to the point A(xa, ya).
I would propose you use hill climbing. It finds a local minimum in a function with a logarithmic complexity. I will write example c++ code assuming there is a function h(x) that calculates the distance from A to the point with the point with x coordinate equal to x on the parabola.
double minDist() {
const double epsylon = 1e-9; // used to avoid double prescision errors
double current = 0.0;
double step = 1e+6;
while (step > 1e-5) { // change this with the accuracy you need
double left_neighbour = current - step;
double right_neighbour = current + step;
double cval = h(current);
double lval = h(left_neighbour);
double rval = h(right_neighbour);
if (cval < rval + epsylon && cval < lval + epsylon) {
step *= 0.5;
continue;
}
if (lval < rval) {
current = left_neighbour;
} else {
current = right_neighbour;
}
}
return current;
}
In most case you will have a single local mimimum that is the answer you need, but maybe there are cases where you have two(I believe they can not be more then 2). In these cases you need to start the function twice with different initial points.
Hope this helps.
Currently I am writing my thesis and I was confronted with a behavior of .Net C# that I had never seen before. I am talking about an error in a calculation.
I implemented this formula:
1/2 * (Theta i-1 + Theta i) + Sum(Alph k, k=1, i-1)
This formula is applied to 4 objects. Theta is in all objects declared as float with the value 1,5708. Alpha is initialized with 0 and will be increased by each iteration.
First implmentation
float alpha = 0;
float value = 0;
for (int sphereCount = 1; sphereCount < this.spheres.Count; sphereCount++)
{
value = (1/2) * (this.spheres[sphereCount - 1].Theta + this.spheres[sphereCount].Theta);
alpha += value;
}
With this version value is always 0.0!
So I changed it to:
Working implementaion
float alpha = 0;
float value = 0;
for (int sphereCount = 1; sphereCount < this.spheres.Count; sphereCount++)
{
value =(this.spheres[sphereCount - 1].Theta + this.spheres[sphereCount].Theta) * 1/2;
alpha += value;
}
By removing the brackets around the 1/2 and placing it at the end of the calculation it worked.
WHY IS THAT SO???
It seems when you place 1/2 in brackets not depending on the position of 1/2 the result is 0.0. But also when i place (1/2) at the end it results in 0.0.
Does anyone here have an idea why?
This
(1 / 2)
evaluates to 0 because it's integer division. If you say
(1 / 2f)
or
(1 / (float) 2)
you'll be fine because it forces float divsion. Or, even better, just write 0.5.
If you write 1/2 the result is calculated using integer division that gives an integer result. You can force a floating point division by changing one of the numbers to a floating point number, as in 1/2f.
Or you could just write 0.5 which IMHO is more readable than 1/2.
Why multiply by 1? Rather than this:
value =(this.spheres[sphereCount - 1].Theta + this.spheres[sphereCount].Theta) * 1/2;
why not write this:
value =(this.spheres[sphereCount - 1].Theta + this.spheres[sphereCount].Theta) / 2;
You should write 1.0/2 or 0.5 instead 1/2.
1/2 is an integer division which results in an integer 0.
Because 1/2 is treated as integer arithmetic and as such is rounded to 0.
Removing the parenthesis changes the order of operations, and now you are dividing your whole (floating point) formula by two and arriving at a floating point answer.
That's because 1 and 2 are integer values, not floating point values.
When you divide the integer value 1 by the integer value 2, the result is the integer value 0, not the floating point value 0.5.
When you remove the parentheses and change the order of the multiplication, the other part of the expression will first be multiplied by 1, which will implicitly convert the integer value 1 into a floating point value. Then the result is divided by 2, which will also be implicitly converted into a floating point value.
So what you end up doing is:
value = ( (this.spheres[sphereCount - 1].Theta + this.spheres[sphereCount].Theta) * (float)1 ) / (float)2;
Consider this:
double x,y;
x =120.0;
y = 0.05;
double z= x % y;
I tried this and expected the result to be 0, but it came out 0.04933333.
However,
x =120.0;
y = 0.5;
double z= x % y;
did indeed gave the correct result of 0.
What is happening here?
I tried Math.IEEERemainder(double, double) but it's not returning 0 either. What is going on here?
Also, as an aside, what is the most appropriate way to find remainder in C#?
Because of its storage format, doubles cannot store every values exactly as is is entered or displayed. The human representation of numbers is usually in decimal format, while doubles are based on the dual system.
In a double, 120 is stored precisely because it's an integer value. But 0.05 is not. The double is approximated to the closest number to 0.05 it can represent. 0.5 is a power of 2 (1/2), so it can be stored precisely and you don't get a rounding error.
To have all numbers exactly the same way you enter / display it in the decimal system, use decimal instead.
decimal x, y;
x = 120.0M;
y = 0.05M;
decimal z = x % y; // z is 0
You could do something like:
double a, b, r;
a = 120;
b = .05;
r = a - Math.floor(a / b) * b;
This should help ;)
I believe if you tried the same with decimal it would work properly.
http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems can help you understand why you get these "strange" results. There's a particular precision that floating point numbers can have. Just try these queries and have a look at the results:
0.5 in base 2
0.05 in base 2
Modulus should only be used with integer. The remainder come from an euclidean division. With double, you can have unexpected results.
See this article
This is what we use.. :)
public double ModuloOf(double v1, double v2)
{
var mult = 0;
//find number of decimals
while (v2 % 1 > 0)
{
mult++;
v2 = v2 * 10;
}
v1 = v1 * Math.Pow(10, mult);
var rem = v1 % v2;
return rem / Math.Pow(10, mult);
}
I have been working on this for the greater part of the day and I cant seem to make this part of my code work. The intent of the code is to allow the user to input a set of values in order to calculate the missing value. As an additional feature I placed a CheckBox on the form to allow the user to do further calculation. That is where my problem lies. I know the code works because if I change the formula the value that appears in tb3_aic.Text changes per the formula. However, when I use the below the answer does not change like it should. Please reference the attached code. If a jpg image is needed of the formula I can e-mail it.
void Calc3Click(object sender, EventArgs e)
{
if (String.IsNullOrEmpty(tb3_skv.Text) | String.IsNullOrEmpty(tb3_kva.Text) | String.IsNullOrEmpty(tb3_z.Text))
{
MessageBox.Show("Enter all required values", "Missing Data", MessageBoxButtons.OK);
} //If user does not enter all the values required for the calculation show error message box
else
{
if (!String.IsNullOrEmpty(tb3_skv.Text) & !String.IsNullOrEmpty(tb3_kva.Text) & !String.IsNullOrEmpty(tb3_z.Text))
{ //If motor load check box is not checked and required values are entered calculate AIC based on formula.
int y;
decimal x, z, a;
x = decimal.Parse(tb3_skv.Text);
y = int.Parse(tb3_kva.Text);
a = decimal.Parse(tb3_z.Text);
z = (y * 1000) / (x * 1.732050808m) / (a / 100); //the m at the end of the decimal allows for the multiplication of decimals
tb3_aic.Text = z.ToString();
tb3_aic.Text = Math.Round(z,0).ToString();
}
if (cb3_ml.Checked==true)
{//If Motor Load CB is checked calculate the following
int y, b;
decimal x, z, a;
x = decimal.Parse(tb3_skv.Text);
y = int.Parse(tb3_kva.Text);
a = decimal.Parse(tb3_z.Text);
b = int.Parse(tb3_ml.Text);
z = ((y * 1000) / (x * 1.732050808m) / (a / 100))+((b / 100)*(6*y)/(x*1.732050808m)*1000);
tb3_aic.Text = z.ToString();
tb3_aic.Text = Math.Round(z,5).ToString();
}
}
I am grateful for any help that can be provided.
Thank you,
Greg Rutledge
Without really knowing what the problem is, a few things look a bit odd:
Also, mixing decimal and int in a calculation can lead to unexpected results unless you really know what you are doing. I suggest using only decimals (or doubles, which are way faster and usually have enough precision for engineering computations).
You also set tb3_aic.Text twice, I assume you decided on rounding later and forgot to remove the first one.
Edit: This is apparently wrong in C#:
You use bit-wise AND (&) in the if-clause where you probably mean logical AND (&&).
The only difference between them when used with boolean operands are that && short circuits (doesn't evaluate the right operand if the left is false). I learned something, thank you people commenting. :)
Change this:
int y, b;
To this:
int y;
decimal b;
and it works, according to this test:
public void Test2()
{
int y;
decimal b;
decimal x, z, a;
decimal z1, z2;
x = 480m;
y = 2500;
a = 5.75m;
b = 10;
z1 = ((y * 1000) / (x * 1.732050808m) / (a / 100));
z2 = ((b / 100) * (6 * y) / (x * 1.732050808m) * 1000);
z = z1 + z2;
Console.WriteLine("{0}, {1}", z1, z2);
Console.WriteLine(Math.Round(z, 0).ToString());
}
The reason is that integer 10 divided by integer 100 is integer 0, which zero's the whole z2.
I don't know if this is huge but you are setting the text of the tb3_aic textbox twice when maybe you are trying to concatenate?
tb3_aic.Text = z.ToString();
tb3_aic.Text = Math.Round(z,0).ToString();
You seem to be doing this in both methods.
The more that I look at it, this could be an issue since you are setting it in the first if then the second If will overwrite that if the checkbox is checked.
Sample Inputs, first formula
x = 480
y = 2500
a = 5.75
For the first formula the output should be 52296
Sample Inputs, second formula
x = 480
y = 2500
a = 5.75
b = 10
For the first formula the output should be 54100.42
Hope this helps
this line isn't needed, although its not a bug, it just always evaluates to true
if (!String.IsNullOrEmpty(tb3_skv.Text) & !String.IsNullOrEmpty(tb3_kva.Text) & !String.IsNullOrEmpty(tb3_z.Text)) {