ฉันจะแปลงจากองศาเป็นเรเดียนได้อย่างไร


107

ฉันกำลังพยายามแปลงObj-Cรหัสนี้เป็นSwiftรหัส แต่ฉันไม่รู้ว่ารหัสนี้ควรจะเทียบเท่ากับอะไร?

#define DEGREES_TO_RADIANS(degrees)((M_PI * degrees)/180)

ฉัน googled และพบสิ่งนี้

แต่ฉันไม่เข้าใจวิธีการแปลงใน Swift ในกรณีของฉัน?


ฉันคิดว่าคุณไม่มีรหัสบางอย่าง คุณสามารถเพิ่มรหัสที่เกี่ยวข้องทั้งหมดได้หรือไม่? นิยามอื่น ๆ เช่นองศา?
BlackHatSamurai

นี่คือรหัสที่รวดเร็วของฉัน: pastebin.com/bZ4a7EVN
Dharmesh Kheni

คุณช่วยแสดงไฟล์. h ให้ฉันดูได้ไหม
BlackHatSamurai

มันเป็นมาโคร คุณต้องการฟังก์ชัน
gnasher729

คำตอบ:


267

Xcode 11 • Swift 5.1 หรือใหม่กว่า

extension BinaryInteger {
    var degreesToRadians: CGFloat { CGFloat(self) * .pi / 180 }
}

extension FloatingPoint {
    var degreesToRadians: Self { self * .pi / 180 }
    var radiansToDegrees: Self { self * 180 / .pi }
}

สนามเด็กเล่น

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

หากคุณต้องการให้เลขฐานสองจำนวนเต็มส่งคืนประเภททศนิยมแทนที่จะส่งคืน CGFloat เสมอคุณสามารถสร้างวิธีการทั่วไปแทนคุณสมบัติที่คำนวณได้:

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

4
คุณไม่ควรขยายCGFloat?
Zorayr

1
@Zorayr อัปเดตเป็น Swift 3 และการขยาย FloatingPoint จะขยายเวลาทั้งหมด
Leo Dabus

3
จริงๆแล้วใน Swift 3 คุณสามารถใช้ประเภทการวัดผลได้และคุณไม่จำเป็นต้องรู้สูตรการแปลงเลย!
Matt

3
หมายเหตุเคล็ดลับ superpro นี้อย่างไร ... stackoverflow.com/a/28600210/294884
Fattie

1
การลงคะแนนโดยไม่มีเหตุผลไม่สมเหตุสมผล แสดงความคิดเห็น
Leo Dabus

63

นี่ไม่ใช่สิ่งที่คุณถาม แต่ใน Swift 3 / iOS 10 คุณสามารถใช้ประเภทการวัดและทำการแปลงโดยไม่ต้องรู้สูตร!

let result = Measurement(value: 45, unit: UnitAngle.degrees)
    .converted(to: .radians).value

4
สุดยอด @matt ที่ทำงานอีกครั้งขอบคุณ! น่าเสียดายที่ iOS 10 เท่านั้น
ความหมาย - เรื่อง

สิ่งที่น่าสนใจที่ให้เรเดียน = CGFloat (30.3 * .pi / 180.0) ให้เรเดียน 2 = การวัด (ค่า: 30.3 หน่วย: UnitAngle.degrees) แปลงกลับ (เป็น: .radians) ค่าจะแตกต่างกัน: 0.5288347633542818 และ 0.5288345742619878
Zaporozhchenko Oleksandr

และแน่ใจว่า "'การวัดผล' สามารถใช้ได้เฉพาะบน iOS 10.0 หรือใหม่กว่า"
Zaporozhchenko Oleksandr

42

Apple มีฟังก์ชัน GLKitเหล่านี้สำหรับการแปลง:

func GLKMathDegreesToRadians(_ degrees: Float) -> Float
func GLKMathRadiansToDegrees(_ radians: Float) -> Float

GLKit กำลังจะลงจากเวทีในไม่ช้าเนื่องจากตอนนี้มันคือโลกของ Metal ลาก่อน GL เนื่องจากการย้ายแอป iPad ไปยัง Mac จึงไม่รองรับ GLKit อีกต่อไป!.
Juguang

17
let angle = 45° // angle will be in radians, 45 is in degrees

รวบรวมภายใต้สวิฟท์ 3 ยังคงเก็บค่าทั้งหมดทำการคำนวณทั้งหมดเป็นเรเดียนด้วย CGFloats ... แต่ทำให้โค้ดอ่านง่ายขึ้นโดยมีค่าคงที่เป็นองศา ตัวอย่างเช่น 90 ° เครื่องหมาย°จะทำการแปลงองศาเป็นเรเดียนอย่างน่าอัศจรรย์

วิธีตั้งค่านี้:

กำหนดและใช้ตัวดำเนินการ postfix สำหรับเครื่องหมาย° ตัวดำเนินการนี้จะทำการแปลงจากองศาเป็นเรเดียน ตัวอย่างนี้ใช้สำหรับ Ints ให้ขยายสิ่งเหล่านี้สำหรับประเภท Float หากคุณมีความต้องการ

postfix operator °

protocol IntegerInitializable: ExpressibleByIntegerLiteral {
  init (_: Int)
}

extension Int: IntegerInitializable {
  postfix public static func °(lhs: Int) -> CGFloat {
    return CGFloat(lhs) * .pi / 180
  }
}

ตัวอย่างการใช้งานบางส่วน:

let angle = 45°

contentView.transform = CGAffineTransform(rotationAngle: 45°)

let angle = 45
contentView.transform = CGAffineTransform(rotationAngle: angle°)

คำเตือน!

มันง่ายเกินไปที่จะใช้การแปลงนี้สองครั้ง (สำหรับค่าที่มีหน่วยเรเดียนโดยไม่ได้ตั้งใจ) คุณจะได้ผลลัพธ์เป็นตัวเลขที่น้อยมากและดูเหมือนว่ามุมผลลัพธ์จะเป็นศูนย์เสมอ ... อย่าใช้°เหมือนกัน มูลค่าสองครั้ง (อย่าแปลงสองครั้ง) !!:

// OBVIOUSLY WRONG!
let angle = 45°° // ° used twice here

// WRONG! BUT EASY TO MISS
let angle = 45° // ° used here
contentView.transform = CGAffineTransform(rotationAngle: angle°) // ° also used here

IntegerInitializableโปรโตคอลไม่มีจุดหมาย Int แล้วสอดคล้องกับExpressibleByIntegerLiteral
Leo Dabus

Btw คุณสามารถทำให้ตัวดำเนินการนี้เป็นแบบทั่วไปเพื่อรองรับจำนวนเต็มและส่งคืน Floating Point ได้เช่นกัน public extension FixedWidthInteger { postfix static func °<T: FloatingPoint>(lhs: Self) -> T { T(lhs) * .pi / 180 } }
Leo Dabus

และก่อนที่คุณจะแสดงความคิดเห็นเกี่ยวกับเรื่องนี้เมื่อสร้างวิธีการทั่วไปคุณจะต้องตั้งค่าประเภทผลลัพธ์อย่างชัดเจนหากคอมไพเลอร์ไม่สามารถสรุปประเภทผลลัพธ์let angle: CGFloat = 45°ได้ แต่ไม่จำเป็นต้องคาดหวังCGFloatหรือFloatingPointประเภทใด ๆCGAffineTransform(rotationAngle: 45°)
Leo Dabus

11

นอกจากนี้ในการแปลงฟรอนเรเดียนเป็นองศา (ถ้าใครสะดุดกับสิ่งนี้ใน google):

var degrees = radians * (180.0 / M_PI)

3

คุณไม่ จำกัด อักขระ ASCII อีกต่อไปเมื่อสร้างชื่อตัวแปรดังนั้นวิธีการใช้ about (alt-p):

typealias RadianAngle = CGFloat

let π = RadianAngle(M_PI)
let π_x_2 = RadianAngle(M_PI * 2)
let π_2 = RadianAngle(M_PI_2)
let π_4 = RadianAngle(M_PI_4)

extension RadianAngle {
    var degrees: CGFloat {
        return self * 180 / π
    }
    init(degrees: Int) {
        self = CGFloat(degrees) * π / 180
    }
}

ตัวอย่างการใช้งาน:

let quarterCircle = RadianAngle(degrees: 90)
print("quarter circle = \(quarterCircle) radians")
// quarter circle = 1.5707963267949 radians

let halfCircle = π
print("half circle = \(halfCircle.degrees) degrees")
// half circle = 180.0 degrees

2

Swift 4.2

คุณสามารถเขียนฟังก์ชันทั่วไปทั่วโลก:

public func radians<T: FloatingPoint>(degrees: T) -> T {
    return .pi * degrees / 180
}

public func degrees<T: FloatingPoint>(radians: T) -> T {
    return radians * 180 / .pi
}

ตัวอย่าง:

let cgFloat: CGFloat = 23.0
let double: Double = 23.0
let float: Float = 23.0
let int: Int = 23

let cgf = radians(degrees: cgFloat) // 0.4014 CGFloat
let d = radians(degrees: double)    // 0.4014 Double
let f = radians(degrees: float)     // 0.4014 Float
let i = radians(degrees: int)       // compile error

ในกรณีที่คุณไม่ต้องการขยายประเภทลอยทั้งหมดของคุณเช่นนี้

extension FloatingPoint { ... }

ทำไมไม่เพียงreturn .pi * degrees / 180?
Leo Dabus

@LeoDabus เพราะTเป็นFloatingPointประเภทและ 180 เป็นIntประเภท คุณไม่สามารถคำนวณประเภทต่างๆได้อย่างรวดเร็ว
Tikhonov Alexander

คุณผิด. Swift สามารถอนุมานประเภทได้ มันทำงานเหมือนกับว่าคุณกำลังขยายประเภท FloatingPoint 180 จะเป็นอะไรก็ได้ ไม่จำเป็นต้องเป็น Int
Leo Dabus

1
FloatingPoint สอดคล้องกับ ExpressibleByIntegerLiteral นั่นคือเหตุผลที่คุณสามารถเขียนได้ 180 ที่นั่น
Leo Dabus

1
180.0 ต้องการ T เพราะ T ไม่จำเป็นต้องเป็น Double สามารถเป็นประเภทจุดลอยตัวใดก็ได้ คุณเริ่มต้นใหม่จากคู่ 180.0 ของคุณ
Leo Dabus

1

ฉันจะใช้หลักการเดียวกันกับ @ t1ser ที่กล่าวมาข้างต้น แต่สร้างส่วนขยายCGFloatเพื่อให้ง่ายต่อการใช้ทศนิยมสำหรับองศาเช่นกัน (ตัวอย่างเช่นคุณอาจมี 23.4 องศา):

extension CGFloat {
    func degrees() -> CGFloat {
        return self * .pi / 180
    }

    init(degrees: CGFloat) {
        self = degrees.degrees()
    }
}

การใช้มันจะค่อนข้างง่ายเช่นกัน (ส่วนใหญ่เป็นเพราะโดยส่วนตัวแล้วฉันไม่รู้วิธีพิมพ์°😜 - ในกรณีที่คุณไม่ได้ทำเช่นกันมันก็เป็นoption+shift+8btw):

let degreesToConvert: CGFloat = 45.7
.
.
.
let convertedDegrees = degreesToConvert.degrees()

หรือใช้ตัวเริ่มต้น:

let convertedDegrees = CGFloat(degrees: 45.3)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.