Subtracting a float from another float does not equal a float? - unity3d

I am coding with the unity scripting API but I don't think that changes anything.
I have a variable playerMovementScript.rightWallX that is a float and is equal to -20.84.
I then have this line of code:
Debug.Log(-21.24f == playerMovementScript.rightWallX - 0.4f);
It always prints false. I feel like I'm missing something obvious cause I'd like to think I'm not THAT new to coding. Any help would be appreciated.

Floating points not accurate. Use them only for fast calculations. If u want to compare 2 floats use if (Mathf.Approximately(floatA,floatB))

The reason it prints false is because you are using the == operator, which checks if 2 things are equal, therefore since you are doing -21.24f == playerMovementScript.rightWallX - 0.4f, the result is unequal and then it prints false. I am pretty sure you meant =, but we all make mistakes.

Related

Nesting a specific recursion in Pari-GP

everyone!
I've posted a similar problem, initially on Stackexchange; it was moved here and can be found at the link: Declaring a functional recursive sequence in Matlab I'm trying to do something similar in this post, but I've figured that Matlab isn't the place to do it. I'll have to use Pari-GP; and at this point there's no two ways about it.
This is essentially a coding project I've made for myself; which is to effectively numerically evaluate a certain construction of the Tetration function. I've been able to code it fairly well in MatLab; the trouble is, as we are dealing with large numbers like e^e^e^e^e^e^e; these short circuit in MatLab. Pari-GP has a much better understanding of numbers which would usually cause overflows; and I'm now fully realizing why it's used consistently by the Tetration community.
Nonetheless, the Matlab code works for small numbers and numbers with a niceness to them (well placed imaginary argument). For completeness of this question; the github repository for the matlab code is https://github.com/JmsNxn92/Recursive_Tetration This isn't the code we want though; I've optimized it further; this isn't up to date totally. But for the purpose of this question, it's enough.
Now, I'm not the best programmer. I haven't programmed since '09, maybe; but I still know my way around. But it's more that I have the framework of coding; and less the actual syntax. Imagine being well acquainted with french philosophy and french writing; but stumbling your words when ordering a cafe.
As to that, I'll stop beating around the bush, and get to the question.
If I define a function beta_function in Pari-GP and write it as,
beta_function(z,l,n) =
{
out = 0;
for(i=0,n-1,
out = exp(out)/(exp(l*(n-i-z)) +1));
out;
}
Everything is good, and it works. Now the code for beta_function in MatLab isn't very different. There's nothing more complex being added. As I originally asked for MatLab, I'm asking again for Pari-GP. This is how to code a function tau_K(z,l,n,k); which is perfectly doable. I'm just missing something obvious.
The code for tau_K(z,l,n,k) in MatLab is attached below. A friendly person on here explained how to do this in MatLab; for those of you interested, I wasn't really defining the recursion properly beforehand. Here is the current MatLab code I'm using,
function f = tau_K(z,l,n,k)
if k == 1
f = -log(1+exp(-l*z));
return
end
f = log(1 + tau_K(z+1,l,n,k-1)./beta_function(z+1,l,n)) - log(1+exp(-l*z));
end
The question is simple. How would one define this recursion in Pari-GP; how do you code this in Pari-GP?
Everything seems to be collapsing towards a return value at 0, when I try to directly translate this code. And honest to god; I know it's just because I'm making some syntax error in how I'm calling the output into the next iteration. I've tried everything I could think of. And the tutorials, they don't seem to be helping. I've tried next to everything. And at this point, I know I'm missing something stupid syntactically.
I'm just hoping someone here would be so helpful as to explain this to me like I'm in kindergarten. I've heard that tail recursion is important here. And if so, how would I code this in? Simply add in a variable which keeps track of everything?
Again, thanks if you got this far into the question.
When asking questions, it would help if you would provide expected output for some specified given arguments, otherwise it is hard to test. I don't know MATLAB, but your functions could be written in PARI:
beta_function(z,l,n)={
my(out = 0);
for(i=0,n-1,
out = exp(out)/(exp(l*(n-i-z)) +1));
out;
}
tau_K(z,l,n,k)={
if(k == 1,
-log(1+exp(-l*z)),
log(1 + tau_K(z+1,l,n,k-1)/beta_function(z+1,l,n)) - log(1+exp(-l*z))
)
}
In the beta_function, it is important to put my() around out = 0. This keeps the variable local to the function. Failure to do this, means that out will be a global variable, and many subtle bugs can arise.
PARI is a functional programming language which means you often don't need to assign things explicitly to temporary variables. For example if will return a value and this can be returned from your tau_K function (in your MATLAB code you assign to a temporary variable f, but in PARI this is not necessary).
There are no issues with calling a function recursively. In this case, tau_K can just call itself as needed.
In the MATLAB program you have ./. I don't know what this means - I have replaced by / which is just the normal division operator.
Before running you will need to set some precision for the numeric operations. The easiest way to achieve this is to enter \p100 at the PARI-GP prompt. (or \p1000 if you need a 1000 decimal digits of precision). It is possible to control precision dynamically, if you need some part of the calculation performed at high precision and other parts at a lower precision or if the precision needs to be dependent on n.

HLSL - asuint of a float seems to return the wrong value

I've been attempting to encode 4 uints (8-bit) into one float so that I can easily store them in a texture along with a depth value. My code wasn't working, and ultimately I found that the issue boiled down to this:
asuint(asfloat(uint(x))) returns 0 in most cases, when it should return x.
In theory, this code should return x (where x is a whole number) because the bits in x are being converted to float, then back to uint, so the same bits end up being interpreted as a uint again. However, I found that the only case where this function seems to return x is when the bits of x are interpreted as a very large float. I considered the possibility that this could be a graphics driver issue, so I tried it on two different computers and got the same issue on both.
I tested several other variations of this code, and all of these seem to work correctly.
asfloat(asuint(float(x))) = x
asuint(asint(uint(x))) = x
asuint(uint(x)) = x
The only case that does not work as intended is the first case mentioned in this post. Is this a bug, or am I doing something wrong? Also, this code is being run in a fragment shader inside of Unity.
After a long time of searching, I found some sort of answer, so I figured I would post it here just in case anyone else stumbles across this problem. The reason that this code does not work has something to do with float denormalization. (I don't completely understand it.) Anyway, denormalized floats were being interpreted as 0 by asuint so that asuint of a denormalized float would always be 0.
A somewhat acceptable solution may be (asuint(asfloat(x | 1073741824)) & 3221225471)
This ensures that the float is normalized, however it also erases any data stored in the second bit. If anyone has any other solutions that can preserve this bit, let me know!

subscript indices must be either positive integers less than 2^31 or logicals

I'm quite new to Matlab/Octave programming, but have this one issue that I can't seem to solve.
I wrote the following which is actually a quite straight forward calculation on an option price using the Black Scholes Formula (just to give you some background). However, I do constantly get the following error msg:
"subscript indices must be either positive integers less than 2^31 or logicals"
One would think that this explaines it quite nicely and I know there've been questions on it before. The thing that causes troubles, however, is that I am not using any kind of subscript index in my code at all.
Here is my code:
function v=BS_LBO_strike_call(s,T,sigma,r,q,l,alpha)
d1=(log(alpha*l./s) + (r-q-0.5*sigma^2)*T)/(sigma*sqrt(T));
d2=(log(alpha*l./s) - (r-q+0.5*sigma^2)*T)/(sigma*sqrt(T));
d3=(log(alpha*l./s) + (r-q+0.5*sigma^2)*T)/(sigma*sqrt(T));
d4=(log(alpha*l./s) + (r-q-0.5*sigma^2)*T)/(sigma*sqrt(T));
v = exp(-r*T)*s(0.5*sigma^2./(r-q)*(l./s).^(2*(r-q)./sigma^2).*normcdf(d1) - 0.5*sigma^2./(r-q)*alpha.^(-2*(r-q)./sigma^2).*exp((r-q).*T).*normcdf(d2) + alpha.exp*((r-q).*T).*normcdf(d3) - (l./s).*normcdf(d4));
So, I can't seem to figure out what doesn't work out for Octave.
I would highly appreciate if you could maybe shed some light on this. I'm convinced there must be something minor that I overlook
The source of your issues lies in your last line. You have the following:
v = exp(-r * T) * s(0.5 * sigma^2 ....
I think that you have omitted an * between the s and the opening parenthesis because as it is now, everything after that parenthesis is being treated as a subscript into s. This is the root cause of the error you are getting because what follows is likely not an integer or logical.
There is one other point in that line that is likely going to lead to some errors as well. You have the following as part of that statement.
alpha.exp*((r-q).*T) ...
Unless alpha is a struct (I'm sure it's not because you haven't used it that way previously), you will likely want something else besides the . between alpha and exp. Maybe another *?

Logical indexing and double precision numbers

I am trying to solve a non-linear system of equations using the Newton-Raphson iterative method, and in order to explore the parameter space of my variables, it is useful to store the previous solutions and use them as my first initial guess so that I stay in the basin of attraction.
I currently save my solutions in a structure array that I store in a .mat file, in about this way:
load('solutions.mat','sol');
str = struct('a',Param1,'b',Param2,'solution',SolutionVector);
sol=[sol;str];
save('solutions.mat','sol');
Now, I do another run, in which I need the above solution for different parameters NewParam1 and NewParam2. If Param1 = NewParam1-deltaParam1, and Param2 = NewParam2 - deltaParam2, then
load('solutions.mat','sol');
index = [sol.a]== NewParam1 - deltaParam1 & [sol.b]== NewParam2 - deltaParam2;
% logical index to find solution from first block
SolutionVector = sol(index).solution;
I sometimes get an error message saying that no such solution exists. The problem lies in the double precisions of my parameters, since 2-1 ~= 1 can happen in Matlab, but I can't seem to find an alternative way to achieve the same result. I have tried changing the numerical parameters to strings in the saving process, but then I ran into problems with logical indexing with strings.
Ideally, I would like to avoid multiplying my parameters by a power of 10 to make them integers as this will make the code quite messy to understand due to the number of parameters. Other than that, any help will be greatly appreciated. Thanks!
You should never use == when comparing double precision numbers in MATLAB. The reason is, as you state in the the question, that some numbers can't be represented precisely using binary numbers the same way 1/3 can't be written precisely using decimal numbers.
What you should do is something like this:
index = abs([sol.a] - (NewParam1 - deltaParam1)) < 1e-10 & ...
abs([sol.b] - (NewParam2 - deltaParam2)) < 1e-10;
I actually recommend not using eps, as it's so small that it might actually fail in some situations. You can however use a smaller number than 1e-10 if you need a very high level of accuracy (but how often do we work with numbers less than 1e-10)?

Mean of Very Small Values

I'm trying to compute the log of the mean of some very small values. For the current data set, the extreme points are
log_a=-1.6430e+03;
log_b=-3.8278e+03;
So in effect I want to compute (a+b) / 2, or log((a+b)/2) since I know (a+b)/2 is too small to store as a double.
I considered trying to pad everything by a constant, so that instead of storing log_a I'd store log_a+c, but it seems that aand b are far enough apart that in order to pad log_b enough to make exp(log_b+c) computable, I'd end up making exp(log_a+c) too large.
Am I missing some obvious way to go about this computation? As far as I know MATLAB won't let me use anything but double precision, so I'm stumped as to how I can do this simple computation.
EDIT: To clarify: I can compute the exact answer for these specific values. For other runs of the algorithm, the values will be different and might be closer together. So far there have been some good suggestions for approximations; if an exact solution isn't practical, are there any other approximations for more general numbers/magnitudes of values?
Mystical has the right idea but for a more general solution that gives you the log of the arithmetic mean of a vector log_v of numbers already in the log domain use:
max_log = max(log_v);
logsum = max_log + log(sum(exp(log_v-max_log)));
logmean = logsum - log(length(log_v));
This is a common problem in statistical machine learning, so if you do a Google search for logsum.m you'll find a few different versions of MATLAB functions that researchers have written for this purpose. For example, here's a Github link to a version that uses the same calling conventions as sum.
Well, exp(log_b) is so much smaller than exp(log_a) that you can completely ignore that term and still get the correct answer with respect to double-precision:
exp(log_a) = 2.845550077506*10^-714
exp(log_b) = 4.05118588390*10^-1663
If you are actually trying to compute (exp(log_a) + exp(log_b)) / 2, the answer would underflow to zero anyways. So it wouldn't really matter unless you're trying to take another logarithm at the end.
If you're trying compute:
log((exp(log_a) + exp(log_b)) / 2)
Your best bet is to examine the difference between log_a and log_b. If the difference is large, then simply take the final value as equal to the larger term - log(2) since the smaller term will be small enough to completely vanish.
EDIT:
So your final algorithm could look like this:
Check the magnitudes. If abs(log_a - log_b) > 800. Return max(log_a,log(b)) - log(2).
Check either magnitude (they will be close together at this point.). If it is much larger or smaller than 1, add/subtract a constant from both log_a and log_b.
Perform the calculation.
If the values were scaled in step 2. Scale the result back.
EDIT 2:
Here's an even better solution:
if (log_a > log_b)
return log_a + log(1 + exp(log_b - log_a)) - log(2)
else
return log_b + log(1 + exp(log_a - log_b)) - log(2)
This will work if log_a and log_b are not too large or are negative.
Well, if you don't like my previous suggestion of completely changing platforms and are looking for an approximation, why not just use the geometric mean (exp((log_a+log_b)/2) instead?
Use http://wolframalpha.com . For example, as discussed by Mysticial, your calculation of
log(exp(-1.6430e+03) + exp(-3.8278e+03)/2) is approximately equal to log_a. More precisely it equals...
1642.9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999288154175193167154874243862288962865800888654829363675488466381404578225092913407982036991983506370017587380105049077722517705727311433458060227246074261903850589008701929721367650576354241270720062760800558681236724831345952032973775644175750495894596292205385323394564549904750849335403418234531787942293155499938538026848481952030717783105220543888597195156662520697417952130625416040662694927878196360733032741542418365527213770518383992577797346467266676866552563022498785887306273550235307330535082355570343750317349638125974233837177558240980392298326807001406291035229026016040567173260205109683449441154277953394697235601979288239733693137185710713089424316870093563207034737497769711306780243623361236030692934897720786516684985651633787662244416960982457075265287065358586526093347161275192566468776617613339812566918101457823704547101340270795298909954224594...