为三角计算制作Swift假设学位

时间:2015-02-19 03:50:43

标签: ios swift trigonometry

是否可以在Swift for iOS中更改设置,属性等,以便它假定三角计算的度数而不是弧度?

例如,sin(90)将评估为1

我有:

let pi = 3.14 
var r2d = 180.0/pi
var d2r = pi/180

...但是转换对于一些长的三角方程非常重要。

7 个答案:

答案 0 :(得分:27)

正如在其他答案中已经说过的那样,标准库中没有以度为单位的三角函数。

如果您定义自己的功能,那么您可以使用__sinpi()__cospi()等等......而不是乘以π:

// Swift 2:
func sin(degrees degrees: Double) -> Double {
    return __sinpi(degrees/180.0)
}

// Swift 3:
func sin(degrees: Double) -> Double {
    return __sinpi(degrees/180.0)
}

__sinpi manual page(强调添加):

  

在   __sinpi()   函数返回pi乘以x的正弦值(以in为单位测量)   弧度)。这可以比sin(M_PI * x)计算更准确,因为它可以隐含地使用所需的pi位数。        提供全面的结果,而不是M_PI受限的53位。对于大x它可能        也是更有效率,因为所涉及的参数减少非常简单。

__sinpi()并且相关函数是非标准的,但是  适用于iOS 7 / OS X 10.9及更高版本。

示例:

sin(degrees: 180.0)       // 0

给出了精确的结果,与之相反:

sin(180.0 * M_PI/180.0) // 1.224646799147353e-16

只是为了好玩:这就是为所有浮点类型定义基于度的正弦函数的方法,包括CGFloat 函数重载(现在为Swift 3更新):

func sin(degrees: Double) -> Double {
    return __sinpi(degrees/180.0)
}

func sin(degrees: Float) -> Float {
    return __sinpif(degrees/180.0)
}

func sin(degrees: CGFloat) -> CGFloat {
    return CGFloat(sin(degrees: degrees.native))
}

在最后一个变体中,编译器自动从中推断 要调用的函数的实际类型degrees.native,这样就可以了 在32位和64位平台上都能正常工作。

答案 1 :(得分:7)

添加扩展名以清楚地识别这种价值将是处理此类事情的适当方式:

import Darwin // needed to get M_PI
extension Double {
  public var degrees: Double { return self * M_PI / 180 }
  public var ㎭: Double { return self * 180 / M_PI }
}

将它放入游乐场,看看你如何得到你期望的结果:

sin(90.degrees)  --> 1.0
1.㎭  -->  57.2957795130823
1.㎭.degrees --> 1.0
(M_PI / 3).㎭  -->  60.0

答案 2 :(得分:3)

您可以定义返回度数值的全局函数。只需将函数放在任何类之外的swift文件中。

func sind(degrees: Double) -> Double {
    return sin(degrees * M_PI / 180.0)
}

所以你可以在项目的任何地方使用:

sind(90) // Returns 1

答案 3 :(得分:2)

没有设置或属性可以更改内置三角函数。如果您想简化表达式,或者定义自己的sindegcosdeg等,则应该严格按弧度工作。

每个浮点类型都有一个名为static的内置pi成员,其值是π的最佳近似值。例如:Double.piFloat.piCGFloat.pi

此外,sin90˚为1,而不是0。

答案 4 :(得分:2)

它在游乐场中运行,并提供度/弧度单位的类型安全实现。类型定义可以从Swift evolution邮件列表中的here免费获取,并附带一些小的语法修复。我写了一些trig函数;其余的是我所展示的直接延续。

import Cocoa

//MARK:- AngleType    
protocol AngleType: FloatLiteralConvertible, IntegerLiteralConvertible {
    var value: Double { get set }

    init(_ value: Double)
    init(_ value: Int)
    init<T: IntegerType>(integerLiteral value: T)
    init<T: FloatingPointType>(floatLiteral value: T)
}


// Implement FloatLiteralConvertible and IntegerLiteralConvertible
extension AngleType {
    init<T: IntegerType>(integerLiteral value: T) {
        self.init(value)
    }

    init<T: IntegerType>(_ value: T) {
        self.init(integerLiteral: value)
    }

    init<T: FloatingPointType>(floatLiteral value: T) {
        self.init(value)
    }

    init<T: FloatingPointType>(_ value: T) {
        self.init(floatLiteral: value)
    }
}

//MARK:- Degree
struct Degree: AngleType {
    typealias FloatLiteralType = Double
    typealias IntegerLiteralType = Int

    var value: Double

    init(_ value: Double) {
        self.value = value
    }

    init(_ value: Int) {
        self.value = Double(value)
    }
}

protocol DegreeConvertible {
    init(degreeLiteral value: Degree)
}

extension Degree: CustomStringConvertible, CustomDebugStringConvertible {
    var description: String {
        return self.value.description
    }

    var debugDescription: String {
        return "\(self.value.description)°"
    }
}

extension Degree: RadianConvertible {
    init(radianLiteral value: Radian) {
        self.value = Double(radianLiteral:value) * 180.0 / M_PI
    }

    init(_ value: Radian) {
        self.init(radianLiteral: value)
    }
}

//MARK:- Radian
struct Radian: AngleType {
    typealias FloatLiteralType = Double
    typealias IntegerLiteralType = Int

    var value: Double

    init(_ value: Double) {
        self.value = value
    }

    init(_ value: Int) {
        self.value = Double(value)
    }
}

protocol RadianConvertible {
    init(radianLiteral value: Radian)
}

extension Radian: CustomStringConvertible, CustomDebugStringConvertible {
    var description: String {
        return self.value.description
    }

    var debugDescription: String {
        return "\(self.value.description)㎭"
    }
}

extension Radian: DegreeConvertible {
    init(degreeLiteral value: Degree) {
        self.value = Double(degreeLiteral: value) * M_PI / 180.0
    }

    init(_ value: Degree) {
        self.init(degreeLiteral: value)
    }
}

//MARK:- Adding Conformance To Built In Types
extension FloatLiteralType: DegreeConvertible, RadianConvertible {
    init(degreeLiteral degree: Degree) {
        self = degree.value
    }

    init(radianLiteral radian: Radian) {
        self = radian.value
    }
}

extension CGFloat: DegreeConvertible, RadianConvertible {
    init(degreeLiteral degree: Degree) {
        self.init(degree.value)
    }

    init(radianLiteral radian: Radian) {
        self.init(radian.value)
    }

    init(_ degree: Degree) {
        self.init(degreeLiteral: degree)
    }

    init(_ radian: Radian) {
        self.init(radianLiteral: radian)
    }
}

func sin(value: Radian) -> Double { return sin(Double(value.value)) }
func asin(value: Double) -> Radian { return Radian(Double(asin(value))) }
func cos(value: Radian) -> Double{ return cos(Double(value.value)) }
func acos(value: Double) -> Radian { return Radian(Double(acos(value))) }


func sin(value: Degree) -> Double{ return sin(Radian(value)) }
func asin(value: Double) -> Degree { return Degree(Double(asin(value))) }
func cos(value: Degree) -> Double{ return cos(Radian(value)) }
func acos(value: Double) -> Degree { return Degree(Double(acos(value))) }

let d180: Degree = Degree(180.0)
let r180: Radian = Radian(degreeLiteral: d180)

let d0 = Degree(0.0)
let r0 = Radian(d0)

let dsin180 = sin(d180)
let rsin180 = sin(r180)
let dcos180 = cos(d180)
let rcos180 = cos(r180)

let dsin0 = sin(d0)
let rsin0 = sin(r0)
let dcos0 = cos(d0)
let rcos0 = cos(r0)

let adsin180: Degree = asin(dsin180)
let adcos180: Degree = acos(dcos180)

答案 5 :(得分:1)

我不完全确定您为什么要重载默认的全局方法,但如果必须,您可以提供备用方法签名:

func sin(#degrees: Double) -> Double { // Require a parameter name for method call
    let radians: Double = degrees * (M_PI / 180) // Convert to rad
    return sin(radians) // Return result of default method call with automatic conversion
}

sin(degrees: 90) // 1.0
sin(degrees: 180) // 0.0

然而,这实际上是一种奇怪的方式,而且以类似的方式明确定义自己的方法(这是他们所要做的)会更有意义:

func sinFromDegrees(degrees: Double) -> Double {
    let radians: Double = degrees * (M_PI / 180)
    return sin(radians)
}

sinFromDegrees(90) // 1.0
sinFromDegrees(180) // 0.0

答案 6 :(得分:1)

因为我经常使用trig。我发现最好的方法是在class ViewController之外定义一些函数。

如果您在imports正下方和class ViewController:UIViewController { }正上方的任何一个.swift文件中定义它们,那么您可以在整个项目中调用它们。

因此对于sin函数,我将它命名为sindeg()代表&#34; sin度&#34;。

func sindeg(degrees: Double) -> Double {
    return sin(degrees * M_PI / 180.0)
    }

所以这需要你的学位数转换它,解决它并以度数返回。 所以你需要做的就是输入sindeg(45.5),结果将是0.71325045.

以下是其他人:

func cosdeg(degrees: Double) -> Double {
    return cos(degrees * M_PI / 180.0)
}
func tandeg(degrees: Double) -> Double {
    return tan(degrees * M_PI / 180.0)
}
这里的arcTan非常相似,唯一不同的是返回公式

 func atanDegree(degrees: Double) -> Double {
        return atan(degrees) * 180 / M_PI
    }

这只是将弧度值转换为度数。接受弧度,转换,返回度数。

func Convert(radians: Double) -> Double {
    return radians * 180.0 / M_PI
}