【问题标题】:Make Swift Assume Degrees for Trigonometry Calculations为三角函数计算快速假设度数
【发布时间】:2015-04-20 07:42:54
【问题描述】:

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

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

我有:

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

...但是对于一些长三角方程,转换确实涉及到了。

【问题讨论】:

  • 您可以创建以度为单位的参数并将其转换为弧度并返回已定义函数的结果的新函数。
  • “但是转换确实涉及到一些长三角方程”我同意@rakeshbs - 这就是为什么上帝给了你函数,所以你可以随时自动转换而无需做任何事情“参与”。
  • 是的,但上帝以弧度工作,而不是度数。

标签: ios swift trigonometry


【解决方案1】:

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

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

另外,sin 90˚ 是 1,而不是 0。

【讨论】:

    【解决方案2】:

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

    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
    

    【讨论】:

      【解决方案3】:

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

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

      因此,您可以在项目中的任何地方使用:

      sind(90) // Returns 1
      

      【讨论】:

        【解决方案4】:

        添加扩展以清楚地识别值的种类是处理此类事情的合适方法:

        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
        

        【讨论】:

          【解决方案5】:

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

          如果您定义自己的函数,那么您可以使用__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 的正弦值(以 弧度)。这可以比 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 位平台上都能正常工作。

          【讨论】:

          • 嘿@MartinR __sinpi 必须是整个网站上最好的“专业提示”之一。我送了一笔赏金作为感谢。制造
          • 这是一个很棒且描述良好的答案
          【解决方案6】:

          看到我经常使用三角。我发现最好的方法是在class ViewController 之外定义一些函数。

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

          所以对于 sin 函数,我将其命名为 sindeg() 代表“sin 度数”。

          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
          }
          

          【讨论】:

            【解决方案7】:

            这在操场上运行,并提供度数/弧度单位的类型安全实现。类型定义免费取自 Swift Evolution 邮件列表上的 here,并进行了一些小的语法修复。我写了一些三角函数;其余的都是我所展示的内容的直接延续。

            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)
            

            【讨论】:

              猜你喜欢
              • 2017-01-13
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多