Trigonometric functions in Swift
The problem with sine and cosine functions is that M_PI is an irrational number is approximately defined as 3.14159265358979323846264338327950288
which means that it has some error.
One possible solutions to your problem is having the ranges of input form -PI/2 to PI/2. This reduces the error of approximation. The following changes your range to -90 to 90 degrees.
sin(((fmod($0, 360) > 270 ? fmod($0, 360) - 270 : ((fmod($0, 360) > 90) ? 180 - fmod($0, 360) : fmod($0, 360))) * M_PI / 180.00)) }
Reference from here
Trigonometry Function (cos) Returning Different Value to a Calculator
The Darwin
trig functions work in Radians.
Issue 1.1
print(cos(0)) // receiver error "Ambiguous use of 'cos'"
print(cos(90)) // receiver error "Ambiguous use of 'cos'"
print(cos(180)) // receiver error "Ambiguous use of 'cos'"
print(cos(270)) // receiver error "Ambiguous use of 'cos'"
These are ambiguous because there are two version of cos, which these two types:
(Double) -> Double
(Float) -> Float
Both Double
and Float
conform to ExpressibleByIntegerLiteral
, so both can be expressed by an Int
. It's ambiguous as to which of the two types the Int
should express.
If you want the Double
version, you can call it with:
cos(0 as Double)
cos(0.0)
because direct use of a floatliteral as aDouble
takes precedence over a conversion viaexpressiblebyfloatliteral
.
If you want the Float version
, you can call it with: cos(0 as Float)
In both cases, the ambiguity can be resolved if context provides sufficient information. For example:
functionThatTakesADouble(cos(0)) // will use the `(Double) -> Double` version
functionThatTakesAFloat(cos(0)) // will use the `(Float) -> Float` version
print(cos(M_PI*0)) // M_PI is a Double, so 0 is treated as a Double
Issue 1.2
After resolving the type ambiguity, like so:
print(cos(0.0)) // 1.0
print(cos(90.0)) // -0.44807361612917
print(cos(180.0)) // -0.598460069057858
print(cos(270.0)) // 0.984381950632505
We get correct answers. Remember, the system trig functions work in radians.
Issue 2
print(cos(M_PI*0)) // returns 1
print(cos(M_PI*1)) // returns -1
print(cos(M_PI*2)) // returns 1
print(cos(M_PI*3)) // returns -1
These are all correct values.
Issue 3
print(cos(M_PI*0)) // returns 1
print(cos(M_PI*90)) // returns 1
print(cos(M_PI*180)) // returns 1
print(cos(M_PI*270)) // returns 1
These are also correct. cos
is 1
for every even multiple of pi
radians.
Issue 4
print(cos(M_PI/M_PI-1)) // returns 1
print(cos(M_PI/M_PI+89)) // returns -0.44
print(cos(M_PI/M_PI+179)) // returns -0.59
print(cos(M_PI/M_PI+269)) // reutnrs 0.98
M_PI/M_PI
is 1.0
(as a Double
), so these cases are equivalent to the first, but with the extra type information necessary to allow the compiler to unambiguously choose (Double) -> Double
cos
over (Float) -> Float
.
How can I convert from degrees to radians?
Xcode 11 • Swift 5.1 or later
extension BinaryInteger {
var degreesToRadians: CGFloat { CGFloat(self) * .pi / 180 }
}
extension FloatingPoint {
var degreesToRadians: Self { self * .pi / 180 }
var radiansToDegrees: Self { self * 180 / .pi }
}
Playground
45.degreesToRadians // 0.7853981633974483
Int(45).degreesToRadians // 0.7853981633974483
Int8(45).degreesToRadians // 0.7853981633974483
Int16(45).degreesToRadians // 0.7853981633974483
Int32(45).degreesToRadians // 0.7853981633974483
Int64(45).degreesToRadians // 0.7853981633974483
UInt(45).degreesToRadians // 0.7853981633974483
UInt8(45).degreesToRadians // 0.7853981633974483
UInt16(45).degreesToRadians // 0.7853981633974483
UInt32(45).degreesToRadians // 0.7853981633974483
UInt64(45).degreesToRadians // 0.7853981633974483
Double(45).degreesToRadians // 0.7853981633974483
CGFloat(45).degreesToRadians // 0.7853981633974483
Float(45).degreesToRadians // 0.7853981
Float80(45).degreesToRadians // 0.78539816339744830963
If you would like to make the binary integer return a floating point type instead of always returning a CGFloat you can make a generic method instead of a computed property:
extension BinaryInteger {
func degreesToRadians<F: FloatingPoint>() -> F { F(self) * .pi / 180 }
}
let radiansDouble: Double = 45.degreesToRadians() // 0.7853981633974483
let radiansCGFloat: CGFloat = 45.degreesToRadians() // 0.7853981633974483
let radiansFloat: Float = 45.degreesToRadians() // 0.7853981
let radiansFloat80: Float80 = 45.degreesToRadians() // 0.78539816339744830963
Swift calculating a new point x distance in y direction
Here are a few clues:
sin()
takes radians not degrees, so you need to convert.0
is right, not up so you need to adjust for that.- use
cos()
for horizontal.
This is closer to what you need:
public func offset(byDistance distance:CGFloat, inDirection degrees:CGFloat) {
let radians = (degrees - 90) * .pi / 180
let vertical = sin(radians) * distance
let horizontal = cos(radians) * distance
self.position = self.position.applying(CGAffineTransform(translationX:horizontal, y:vertical))
}
Math function returns wrong value
The calculation is correct. However sin
and cos
take their param in radians, not degrees.
In calculus and most other branches of mathematics beyond practical
geometry, angles are universally measured in radians. One radian is
equal to 180/π degrees.To convert from radians to degrees, multiply by 180/π.
https://en.wikipedia.org/wiki/Radian
RPN calculator (Swift xcode) - sine, cosine, tangent, reciprocal (1/x), log (base) functions
Here is an implementation of those basic functions in Swift. I'll let you put that into your RPN calculator, since that is your assignment.
The built-in trig functions need input in radians, so you have to convert by multiplying by pi
and dividing by 180.0
.
func sine(degrees: Double) -> Double {
return sin(degrees * M_PI / 180)
}
func cosine(degrees: Double) -> Double {
return cos(degrees * M_PI / 180)
}
func tangent(degrees: Double) -> Double {
return tan(degrees * M_PI / 180)
}
func log(n: Double, base: Double) -> Double {
return log(n) / log(base)
}
func reciprocal(n: Double) -> Double {
return 1.0 / n
}
For log(base 10) just use the built-in log10(n: Double) -> Double
Related Topics
Perform Segue with Identifier Wont Work in Swift 2
How to Get Vcf Data with Contact Images Using Cncontactvcardserialization Datawithcontacts: Method
Using Private API to Read Wifi Rssi Value
Is Char Signed or Unsigned by Default on iOS
iOS Share Gif (Animated Image) Not Working
Font Descriptor Returns Nil in iOS 8
How to Convert Cmsamplebuffer to Data in Swift
Date Formats from Device Based on Locale
This Code Signature Is No Longer Supported When Building App on iPhone 12
iOS 10: How to Show Incoming Voip Call Notification When App Is in Background
Convert Unicode (E.G. 1F564) to Emoji in Swift
Extension for Uicolor with Custom Colors It Is Real
Addarc(Withcenter) Closing Path
Ibm Worklight 6.1 - Failed Re-Generating the iPhone Native Folder