I wrote this test code:
NSLog(#"%g", tan(M_PI / 2.0));
and the output of the console is:
1.63312e+16
The issues is about approximation, right? Did I make some mistakes or the tan function of math.h really doesn't handle this case itself (returning me INFINITY) ? shall I handle theese input cases myself (example: when I get pi/2 input value I return an error message) or is there a better (more elegant) way to get the correct value ?
Thanks
Its because M_PI != real pi because it cannot be represented, so what you get from M_PI is approximation of pi, which its tangent is what you get.
Edit: the following:
printf("cos(M_PI / 2) = %.30f\nsin(M_PI / 2) = %.30f\n",
cos(M_PI / 2), sin(M_PI / 2));
will print
cos(M_PI / 2) = 0.000000000000000061232339957368
sin(M_PI / 2) = 1.000000000000000000000000000000
Which shows cos(pi / 2) is non-zero.
Doing the division will give
1.63312393531953E16
which is exactly what you get.
Related
I am trying to calculate the expected "score" for a given player in an elo system*.
The problematic line of code is as follows:
expected(0) = (1 / (1 + (10 ^ (1000 - 1000) / 400)))
When I return the value of expected(0) directly after this line as a msgbox in a windows forms application, it states the value to be 11 even though it should be 1 (expected(1) is declared as an array of integers).
When I run this same line of code in a console application, it returns 1.
Is there any reason why this line of code is instead returning 11?
Edit: The exact code of the subroutines for both the console application that I tested (which returns correct value) and the forms application:
Forms:
Dim expected(1) As Integer
expected(0) = (1 / (1 + (10 ^ (1000 - 1000) / 400)))
Msgbox(expected(0))
Console:
Dim t(1) As Integer
t(0) = (1 / (1 + (10 ^ (1000 - 1000) / 400)))
Console.WriteLine(t(0))
Console.ReadLine()
The above numeric values (e.g. 400, 1000) are literally written in to the program like that, as I was just testing whether they work.
*you can look up the equation on the wikipedia page "Elo rating system" but I don't think it is important in this situation. In this situation I am simulating both players Elo being 1000.
Apologies to anyone who was scratching their head at this, but the solution was very simple and the problem was 100% my fault. As it turns out msgbox(expected(0) was actually written as msgbox("expected 1" & expected(0)) which came out in the box as "expected 11" rather than "1" or "expected 1 1". I thought 11 was the value. Apologies again.
Your formula from Wikipidia is:
One way to code this accurately:
Dim d1 As Double = (Rb - Ra) / 400R '0
Dim d2 As Double = 1 + System.Math.Pow(10, d1) '2
Dim EA As Double = 1 / d2 '0.5
Your expression:
(1 / (1 + (10 ^ (1000 - 1000) / 400)))
Is not an accurate translation of the source forumul above, your expression above returns zero instead of 0.5. If EA is an integer, value you will get the same result from both calculations, but I think you should always get the correct value then explicitly manipulate it rather manipulating it implicitly (by the compiler, for instance).
I have 2 degree-to-radian functions pre-defined using #define:
Function 1:
#define degreesToRadians(degrees) (M_PI * degrees / 180.0)
Function 2:
#define DEGREES_TO_RADIANS(angle) ((angle) / 180.0 * M_PI)
Only the 2nd function returns correct answer, while the first one provides weird answer. What are the differences between them?
Non of the two "functions" mentioned above is a functions, they are macros, and the first macro is not safe, for example, expanding the macro degreesToRadians(10 + 10) gives (M_PI * 10 + 10 / 180.0), which is interpreted as ((M_PI * 10) + (10 / 180.0)) and this is clearly wrong. While expanding DEGREES_TO_RADIANS(10 + 10) gives ((10 + 10 ) / 180.0 * M_PI) which is correct.
The other difference is that M_PI * degreess might overflow the double boundaries, and thus give a wrong answer (but this requires a rather high value in degrees)
The calculations are pretty much identical, notwithstanding floating point limitations. However, you have angle surrounded with parentheses in the second macro, which is the right thing to do.
In the first macro, if you do:
x = degreesToRadians(a + 45);
then, remembering that macros are simple text substitutions, you'll end up with:
x = (M_PI * a + 45 / 180.0);
which will not end well, since it will be calculated as if you'd written:
x = (M_PI * a) + (45 / 180.0);
In other words, you simply multiply the angle by PI and add a constant 0.25.
If instead you change the first one to be:
#define degreesToRadians(degrees) (M_PI * (degrees) / 180.0)
then it should begin to behave a little better.
The other difference has to do with either large or small values of the angle. A divide-then-multiply on a small angle (and I mean really small like 10-308, approaching the IEEE754 limits) may result in a zero result while a multiply-then-divide on a large angle (like 10308) may give you overflow.
My advice would be to ensure you use "normal" angles (or normalise them before conversion). Provided you do that, the different edge conditions of each method shouldn't matter.
And, in all honesty, you probably shouldn't even be using macros for this. With insanely optimising compilers and enumerations, macros should pretty much be relegated to conditional compilation nowadays. I'd simply rewrite it as a function along the lines of:
double degreesToRadians(double d) {
return M_PI * d / 180.0;
}
Or, you could even adjust the code so as to not worry about small or large angles (if you're paranoid):
double degreesToRadians(double d) {
if ((d > -1) && (d < 1))
return (M_PI * d) / 180.0;
return (d / 180.0) * M_PI;
}
Here is the code:
float passedPrice = 2.953;
float placed = 1000.0; //3 decimals
NSLog("%f", placed); // Gives 2953;
float withNoFractions = floorf(passedPrice * placed);
The value stored in withNoFractions is 2952! It shall be 2953. What is really strange is that it works some time.
Many decimal floating point fractions cannot be represented as exact fractions in binary, so they have to be approximated. 2.953 is being approximated as something like 2.95299999. When you multiply by 1000, the result is 2952.99999, and when you get the floor of this, it's 2952.
To solve this, you can either use round() instead of ffloorf(), or you can add 0.5 before calling ffloorf():
float withNoFractions = floorf(passedPrice * placed + 0.5);
I am working on a calculation for free space loss and hitting a snag.
Doing this calculation:
fslLoss = 36.6 + (20 * log(fromAntenna/5280)) + (20 * log(serviceFreq))
Where fslLoss is a float and fromAntenna and servicefreq are integers:
NSLog(#"the freespace Loss is %0.01f", fslLoss);
The result is "the freespace Loss is -inf"
The issue appears to be in the 20log(fromAntenna/5280) section, as I get normal results without it.
BTW ... tried log10 with the same results.
Thanks for the help,
padapa
You say fromAntenna is an integer, so fromAntenna/5280 will be calculated with integer arithmetic. That means it will be rounded (floored, technically), probably not what you intended.
Fix it with:
log( (double) fromAntenna / 5280.0 )
log(0) is -inf. The integer division inside the logarithm may be zero. Use fromAntenna/5280.0 to get float division.
The compiler is correctly using fromAntenna & serviceFreq as ints and that's not giving you good results when fslLoss is a float. Use some float casts and you'll have better luck:
fslLoss = 36.6 + (20 * log((float)fromAntenna/5280)) + (20 * log((float)serviceFreq));
I'm trying to write code to draw a clock on the screen of an iOS device. I need to get the angle of a line (seconds, minutes, hours hands of clock) from the current time. My code accurately grabs the time, but for some reason, all of the angles I receive end up being the same (no matter what time it is).
If it helps, the angle I am constantly receiving is:
-1.5707963267948966
Here is the code I use to get the angles:
secondsTheta = ((seconds/60) * (2 * M_PI)) - (M_PI / 2);
minutesTheta = ((minutes/60) + (seconds/3600)) * (2 * M_PI) - (M_PI / 2);
hoursTheta = ((hours/12) + (minutes/720) + (seconds/43200)) * (2 * M_PI) - (M_PI / 2);
My thought is that something is funky with M_PI, but I don't know what would be...but as I said, the seconds, minutes, and hours variables are correct. They are declared in my header file as ints, and I know that [NSDateComponents seconds](etc) returns an NSInteger, but I don't think that should matter for this basic math.
Since the seconds, minutes, and hours variables are declared as ints the division will not give you the correct values. An int divided by another init will result in an int, what is needed for the result is a float. In order to have the compiler use floating point arithmetic it is necessary that one of the operands be a floating point format number (float).
Example: 10 seconds divided by 60 (10/60) will use integer math and result in 0.
Example: 10.0 seconds divided by 60 (10/60) will use floating point math and result in 0.1.66666667.
Example:
secondsTheta = ((seconds/60.0) * (2 * M_PI)) - (M_PI / 2);
or
secondsTheta = (((float)seconds/60) * (2 * M_PI)) - (M_PI / 2);
Your seconds, minutes and hours are ints. Dividing ints by ints does integer arithmetic and truncates the values, so
seconds/60
will always give you 0. Objective C inherits this behavior from C and this is fairly common behavior among programming languages.