I am trying to build a degrees/radians calculator. Here are the functions I have.
func degreesToRadians(degrees: Double) -> Double {
return degrees * (M_PI / 180)
}
func radiansToDegrees(radians: Double) -> Double {
return radians * (180 / M_PI)
}
degreesToRadians(90)
radiansToDegrees(M_PI/4)
degreesToRadians(90) returns 1.5707963267949
radiansToDegrees(M_PI/4) returns 45.0
What I want to happen is in the Degrees to Radians function instead of 1.5707963267949 I want the output to be π/2. Is this even possible?
Thanks.
To represent 90 degrees as π/2, what you want to do is
consider the fraction of degrees over 180 (i.e. numerator of degrees and denominator of 180);
reduce this fraction (i.e. divide both the numerator and denominator by the greatest common factor); in the case of 90/180, the greatest common factor is, in fact, 90, yielding a reduced numerator of 1 and a reduced denominator of 2;
the result as a string representation of the fraction, i.e. something like
"\(reducedNumerator)π/\(reducedDenominator)"
Obviously, if either the numerator or denominator are 1, then you can suppress that portion of the string, but hopefully you get the basic idea.
Take a crack at that.
If you want exactly: "π/2", I don't think this is possible with double. You might get this in String, but not in a number. I think your best option would be to take an optional bool in which case result is returned as multiple of pi.
degreesToRadians(90, resultAsMultipleOfPi:true)
If this bool is true then 0.5 should be returned. You may need to do some rounding off to get well rounded numbers.
If you look closely on what is really M_PI you will see that it is predefined double value in math.h that equals
#define M_PI 3.14159265358979323846264338327950288 /* pi */
If you want more precision you can declare and use long double value instead.
You can directly use M_PI constant.
If you need in float format just use this,
let pi = Float(M_PI)
Related
What is the correct way to perform this operation?
399.9 / 100
What I would expect to see is
3.999
but the result is
3.9989999999999997
The result you see is correct, it's just not what you want.
Doubles are not precise values. The double you get by writing 399.9 is actually the precise value.
399.8999999999999772626324556767940521240234375
That's the closest available double to the exact value 399.9. Any other double is at least as far away from 399.9 as that.
Then you divide by 100. Again, the result is not precise, but the closest double has the exact value
3.99899999999999966604491419275291264057159423828125
That differs from what you would get by writing 3.999, which is the exact value:
3.999000000000000110134124042815528810024261474609375
At every step, the double operations have minimized the error, but because you are doing multiple steps, the final result diverges from the double closest to the mathematical result.
What you need to do depends on what your actual requirements are.
If you want to always calculate with two significant digits, then I'd just multiply my numbers with 100 and do all the operations as integer operations, until the very last division by 100.
If you have an intermediate result and wants to round it to two digits, I'd do what Fy Z1K says:
result = (result * 100).round() / 100;
import 'dart:math';
double roundDouble(double value, int places){
double mod = pow(10.0, places);
return ((value * mod).round().toDouble() / mod);
}
then you would basically get
double num1 = roundDouble(12.3412, 2);
// 12.34
double num2 = roundDouble(12.5668, 2);
// 12.57
double num3 = roundDouble(-12.3412, 2);
// -12.34
double num4 = roundDouble(-12.3456, 2);
// -12.35
To make decimal operations you can use the decimal package.
final d = Decimal.parse;
print(d('399.9') / d('100')); // => 3.999
UInt64 intValue = 999999900;
float tt = intValue;
NSLog(#"float tt = %f", tt);
the output result is "float tt = 999999872", as you can see the UInt64 convert to float lose something, the Max float is bigger than 999999900, so I think the value 999999900 can be cast to float, so my question is why lose 28 in iOS?
float has a limited amount of precision. It's not the size of the number, it's the number of significant digits (9 in this case).
Use double instead of float to get more precision.
UInt64 intValue = 999999900;
double tt = intValue;
NSLog(#"double tt = %f", tt);
Why are you using float and not double? Has nobody told you that float has very limited precision (around 7 digits) while double has about 15 digits?
As a rule, you should NEVER use float instead of double unless you yourself can give a reasonable explanation why float would be more suitable than double.
So your question is: Why do I lose precision when I intentionally throw away 8 digits and precision, and what can I do? The answer is very simple: You lost precision because you threw it away yourself. Use double instead of float.
While I write code like below
NSLog(#"%f",acos(cos(1)));
it returns 1 as result but if I tried to obtain result from degree instead of radian then facing problem as below
#define DEGREES_TO_RADIANS(angle) ((angle) / 180.0 * M_PI)
NSLog(#"%f",acos(cos(DEGREES_TO_RADIANS(1))));
then it returns 0.017453 instead of 1.If I write like below
NSLog(#"%f",acos(cos(DEGREES_TO_RADIANS(1)))*180/M_PI);
then I'm getting proper 1 as result. But if I'll write like below
NSString *a1 = [NSString stringWithFormat:#"%f",(cos(DEGREES_TO_RADIANS(1)))];
NSString *a2 = [NSString stringWithFormat:#"%f",(acos([a1 doubleValue])*180/M_PI)];
NSLog(#"%f",[a2 doubleValue]);
then I'm getting 0.998999 as result.
Then where the problem is?
Please help me
0.017453 is about how many radians are in one degree.
If you want your logging line to output 1, you'll need to convert back to degrees.
#define RADIANS_TO_DEGREES(angle) ((angle) * 180.0 / M_PI)
NSLog(#"%f", RADIANS_TO_DEGREES(acos(cos(DEGREES_TO_RADIANS(1)))));
Note that you may get a result like 0.9999, though, due to the limited accuracy of trigonometric functions, and of floats in general.
Arc Cosine is the inverse of cosine.
Cosine takes an angle as input, and returns a value ranging from -1 to 1.
Arc Cosine (acos) takes a value from -1 to 1 as input, and returns an angle.
The input to acos() is not an angle, so you should not try to convert it between degrees and radians. The result is an angle. That's what you convert.
So you would write
x = RADIANS_TO_DEGREES(acos(1)).
That would give you the angle at which the cosine is 1, expressed in degrees. (The value of acos(1) is 0, which is the same in degrees or radians.)
Better to use acos(0) as a test value. The cosine function = 0 at pi/2 (or 90 degrees.)
So
acos(0) == pi/2. (~1.5707)
RADIANS_TO_DEGREES(acos(0)) == 90.
EDIT:
I see now that in your question you were taking acos(cos(DEGREES_TO_RADIANS(1)), which is correct.
However, you still need to convert the result of acos() to degrees if you want your answer in degrees, as described above. (And Kevin's answer is also correct. My mistake)
Note that cos(1) is a little strange, in both degrees and radians. That isn't going to give an even answer in either.
cos(0) = 1, cos(pi) = -1, cos(2pi) = 1.
(or in degrees)
cos(180) = -1, and cos(360) = 1)
cos(1) in degrees is going to be an strange decimal value, and so will cos(1) in radians.
#import "ViewControllerSettings.h"
#define DEGREES(radians) (radians * 180 / M_PI)
NSLog(#"%f", sinFita);
sinFita = asin(DEGREES(sinFita));
NSLog(#"%f", sinFita);
returns
2014-04-20 22:10:09.916 ---[8561:60b] 0.239580
2014-04-20 22:10:09.920 ---[8561:60b] nan
I require my answer to be in Degreesº, the and doubles are used.
The answer should be 13.86º
asin argument should be in radians and not degrees and the result returned by asin is also in radians so you will need to execute it as follows :
sinFita = DEGREES(asin(sinFita)); // Be aware that sinFita will now be in degrees and not in radians once this line is executed
Result is correct. Go through you calculation step by step. What do you think asin should return when the argument is greater than 1?
Can someone provide a way to produce a random float between -Pi/2 and Pi/2 please?
I've tried...
float angleR = M_PI / arc4random_uniform(1000) - M_PI * 0.5;
But that doesn't work, lol.
float angle = (rand()/(float)RAND_MAX)*PI - PI/2;
You can easily adapt it to use arc4rand function (mind that its maximum value should be 0x100000000).
Something like this should work. If you want your result to be (roughly) uniformly random, you certainly don't want to divide by a uniformly random number (as that will bias you severely toward angles near, in your case, -π/2).
float angleR = ((float)arc4random_uniform(1000) - 500) * M_PI;