Làm cách nào để chuyển đổi từ độ sang radian?


107

Tôi đang cố gắng chuyển đổi Obj-Cmã này sang Swiftmã nhưng tôi không biết mã này tương đương với mã này là gì?

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

Tôi googled và thấy này

Nhưng tôi không hiểu làm thế nào để chuyển đổi điều đó trong Swift trong trường hợp của tôi?


Tôi nghĩ rằng bạn đang thiếu một số mã. Tất cả bạn có thể thêm tất cả các mã liên quan? Bất kỳ định nghĩa nào khác, như độ?
BlackHatSamurai

này là mã nhanh chóng của tôi: pastebin.com/bZ4a7EVN
Dharmesh Kheni

Bạn có thể cho tôi xem tệp .h được không?
BlackHatSamurai

Đó là một macro. Bạn muốn một chức năng.
gnasher729

Câu trả lời:


267

Xcode 11 • Swift 5.1 trở lên

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

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

Sân chơi

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

Nếu bạn muốn đặt số nguyên nhị phân trả về kiểu dấu phẩy động thay vì luôn trả về CGFloat, bạn có thể tạo một phương thức chung thay vì thuộc tính được tính toán:

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
Bạn không nên gia hạn CGFloat?
Zorayr

1
@Zorayr cập nhật để Swift 3 và mở rộng FloatingPoint đang mở rộng ra tất cả chúng
Leo Dabus

3
Trên thực tế, trong Swift 3, bạn có thể sử dụng các loại Đo lường và bạn không cần phải biết công thức chuyển đổi!
matt

3
Tuy nhiên lưu ý mẹo này SuperPro ... stackoverflow.com/a/28600210/294884
Fattie

1
Bỏ phiếu từ chối mà không có lý do không có ý nghĩa gì cả. Đăng nhận xét
Leo Dabus

63

Đây không giống như những gì bạn đã hỏi, nhưng trong Swift 3 / iOS 10, bạn có thể sử dụng loại Đo lường và thực hiện chuyển đổi mà không cần biết công thức!

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

4
@Matt tuyệt vời trong công việc một lần nữa, cảm ơn! Chỉ tiếc là iOS 10.
ý nghĩa-vấn đề

điều thú vị là cho radian = CGFloat (30,3 * .pi / 180,0) cho radians2 = Đo (giá trị: 30,3, đơn vị: UnitAngle.degrees) .convert (thành: .radians). giá trị sẽ khác: 0,5288347633542818 và 0,5288345742619878
Zaporozhchenko Oleksandr

và chắc chắn " 'đo' chỉ có sẵn trên iOS 10,0 hoặc mới hơn"
Zaporozhchenko Oleksandr

42

Apple cung cấp các chức năng GLKit này để chuyển đổi:

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

GLKit sẽ sớm rời sân khấu, vì bây giờ nó là thế giới của Metal, tạm biệt GL. Khi chuyển ứng dụng iPad sang Mac, GLKit không còn được hỗ trợ !.
Juguang

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

Biên dịch theo Swift 3 . Vẫn giữ tất cả các giá trị, thực hiện tất cả các phép tính bằng radian với CGFloats ..., nhưng làm cho mã dễ đọc hơn với các hằng số theo độ. Ví dụ: 90 ° Dấu ° sẽ thực hiện chuyển đổi độ sang radian một cách kỳ diệu.

Cách thiết lập điều này:

Xác định và sử dụng toán tử hậu tố cho dấu ° . Toán tử này sẽ thực hiện chuyển đổi từ độ sang radian. Ví dụ này dành cho Ints, hãy mở rộng chúng cho các loại Float nếu bạn có nhu cầu.

postfix operator °

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

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

Một số ví dụ về cách sử dụng:

let angle = 45°

contentView.transform = CGAffineTransform(rotationAngle: 45°)

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

Cảnh báo!

Quá dễ dàng để sử dụng chuyển đổi này hai lần (trên một giá trị đã được tính bằng radian do nhầm lẫn), bạn sẽ nhận được một số rất nhỏ như kết quả và dường như góc kết quả sẽ luôn bằng 0 ... KHÔNG sử dụng ° trên cùng một giá trị hai lần (không chuyển đổi hai lần) !!:

// 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

IntegerInitializablegiao thức là vô nghĩa. Int đã phù hợp vớiExpressibleByIntegerLiteral
Leo Dabus

Btw Bạn có thể đặt toán tử này chung để hỗ trợ bất kỳ Số nguyên nào và trả về bất kỳ Dấu chấm động nào. public extension FixedWidthInteger { postfix static func °<T: FloatingPoint>(lhs: Self) -> T { T(lhs) * .pi / 180 } }
Leo Dabus

Và trước khi bạn nhận xét về nó khi tạo một phương thức chung, bạn sẽ cần đặt kiểu kết quả một cách rõ ràng nếu trình biên dịch không thể suy ra kiểu kết quả let angle: CGFloat = 45°. Nhưng nó không cần thiết ở nơi nó mong đợi một CGFloathoặc bất kỳ FloatingPointloại nàoCGAffineTransform(rotationAngle: 45°)
Leo Dabus

11

Ngoài ra, để chuyển đổi fron radian sang độ (nếu ai đó tình cờ tìm thấy điều này trên google):

var degrees = radians * (180.0 / M_PI)

3

Bạn không còn bị giới hạn ở các ký tự ASCII khi tạo tên biến nữa, vậy làm thế nào về điều này bằng cách sử dụng π (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
    }
}

Ví dụ sử dụng:

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

Bạn có thể viết các hàm chung chung toàn cầu:

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

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

Thí dụ:

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

Trong trường hợp khi bạn không muốn mở rộng tất cả các loại thả nổi như thế này

extension FloatingPoint { ... }

Tại sao không đơn giản return .pi * degrees / 180?
Leo Dabus

@LeoDabus vì TFloatingPointkiểu và 180 là Intkiểu. Trong thời gian nhanh chóng, bạn không thể thực hiện tính toán trên các loại khác nhau.
Tikhonov Alexander

Bạn sai rồi. Swift có thể suy ra kiểu. Nó hoạt động giống hệt như khi bạn mở rộng loại FloatingPoint. 180 có thể là bất kỳ điều gì. không nhất thiết phải là Int
Leo Dabus.

1
FloatingPoint tuân theo ExpressibleByIntegerLiteral, đó là lý do tại sao bạn có thể viết 180 ở đó
Leo Dabus

1
180.0 cần T vì T không nhất thiết phải là Double. Nó có thể là bất kỳ loại dấu chấm động nào. Bạn khởi tạo một cái mới từ đôi 180.0 của bạn
Leo Dabus

1

Tôi sẽ sử dụng cùng một nguyên tắc @ t1ser đã đề cập ở trên, nhưng tạo một phần mở rộng của CGFloatđể giúp việc sử dụng số thập phân cho độ dễ dàng hơn (ví dụ: bạn có thể có 23,4 độ):

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

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

Sử dụng nó cũng sẽ khá dễ dàng (chủ yếu là vì cá nhân tôi không biết cách gõ ° 😜 - trong trường hợp bạn không làm vậy, đó là option+shift+8btw):

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

Hoặc để sử dụng trình khởi tạo:

let convertedDegrees = CGFloat(degrees: 45.3)

-5

nhanh chóng 2,3

func  kilometersBetween(Place1:CLLocationCoordinate2D , Place2:CLLocationCoordinate2D) -> Double{
    var start = MKMapPointForCoordinate(Place1)
    var finish = MKMapPointForCoordinate(Place2)
    print(MKMetersBetweenMapPoints(start, finish) / 1000)
    return MKMetersBetweenMapPoints(start, finish) / 1000
} 

1
Mặc dù mã này có thể trả lời câu hỏi, nhưng việc cung cấp thêm ngữ cảnh về cách và / hoặc lý do tại sao nó giải quyết vấn đề sẽ cải thiện giá trị lâu dài của câu trả lời.
Nic3500
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.