Dereceden radyana nasıl dönüştürebilirim?


107

Bu Obj-Ckodu koda dönüştürmeye çalışıyorum Swiftama bu kodun eşdeğerinin ne olması gerektiğini bilmiyorum?

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

Ben googled ve bulunan bu

Ama benim durumumda bunu Swift'e nasıl dönüştüreceğimi anlamıyorum?


Sanırım bazı kodlar eksik. İlgili tüm kodu ekleyebilir misiniz? Derece gibi başka tanımlar var mı?
— BlackHatSamurai

bu benim hızlı kodum: pastebin.com/bZ4a7EVN
— Dharmesh Kheni

Bana .h dosyasını gösterebilir misin?
— BlackHatSamurai

Bu bir makro. Bir işlev istiyorsun.
— gnasher729

Yanıtlar:


267

Xcode 11 • Swift 5.1 veya üzeri

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

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

Oyun alanı

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

İkili tamsayının her zaman bir CGFloat döndürmek yerine bir kayan nokta türü döndürmesini istiyorsanız, hesaplanan bir özellik yerine genel bir yöntem yapabilirsiniz:

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
Uzatman gerekmez mi CGFloat?
— Zorayr

1
@Zorayr, Swift 3'e güncellendi ve FloatingPoint'i genişletmek artık hepsini genişletiyor
— Leo Dabus

3
Aslında Swift 3'te Ölçüm türlerini kullanabilirsiniz ve dönüştürme formülünü bilmenize hiç gerek yok!
— mat

3
NOT ANCAK bu superpro ucu ... stackoverflow.com/a/28600210/294884
— fattie

1
Sebepsiz yere oy vermek hiç mantıklı değil. Yorum yap
— Leo Dabus

63

Bu tam olarak istediğiniz şey değil, ancak Swift 3 / iOS 10'da Ölçü türünü kullanabilir ve formülü bilmeden dönüşümü yapabilirsiniz!

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

4
İnanılmaz @matt yine iş başında, teşekkürler! Ne yazık ki sadece iOS 10.
— anlam meseleleri

radyan = CGFloat (30.3 * .pi / 180.0) let radians2 = Ölçüm (değer: 30.3, birim: UnitAngle.degrees) .converted (to: .radians) .value farklı olacaktır: 0.5288347633542818 ve 0.5288345742619878
— Zaporozhchenko Oleksandr

ve emin "'Ölçüm' yalnızca iOS 10.0 veya daha yeni sürümlerde kullanılabilir"
— Zaporozhchenko Oleksandr

42

Apple, dönüştürme için şu GLKit işlevlerini sağlar:

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

GLKit yakında sahneden çıkıyor, çünkü artık Metal'in dünyası, güle güle GL. İPad uygulamasını Mac'e taşırken, GLKit artık desteklenmiyor !.
— Juguang

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

Swift 3 altında derlenir . Yine de tüm değerleri koruyun, CGFloats ile tüm hesaplamaları radyan cinsinden yapın ... ancak sabitler derece cinsinden olacak şekilde kodu daha okunaklı hale getirin. Örneğin: 90 ° ° işareti dereceleri sihirli bir şekilde radyana dönüştürür.

Bu nasıl kurulur:

° işareti için bir sonek operatörü tanımlayın ve kullanın . Bu operatör, dereceden radyana dönüşümü yapacak. Bu örnek Ints içindir, ihtiyacınız varsa bunları Float türleri için de genişletin.

postfix operator °

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

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

Bazı kullanım örnekleri:

let angle = 45°

contentView.transform = CGAffineTransform(rotationAngle: 45°)

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

Uyarı!

Bu dönüşümü iki kez kullanmak çok kolaydır (yanlışlıkla radyan cinsinden bir değerde), sonuç olarak çok küçük bir sayı alacaksınız ve görünüşte ortaya çıkan açı her zaman sıfır olacaktır ... Aynı üzerinde ° KULLANMAYIN değeri iki kez (iki kez dönüştürme) !!:

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

IntegerInitializableprotokol anlamsızdır. Int zaten uygunExpressibleByIntegerLiteral
— Leo Dabus

Btw Bu operatörü herhangi bir Tamsayıyı desteklemek için jenerik yapabilir ve herhangi bir Kayan Noktayı da döndürebilirsiniz. public extension FixedWidthInteger { postfix static func °<T: FloatingPoint>(lhs: Self) -> T { T(lhs) * .pi / 180 } }
— Leo Dabus

Ve genel bir yöntem oluştururken bu konu hakkında yorum yapmadan önce, derleyici ortaya çıkan türü çıkaramazsa sonuç türünü açıkça ayarlamanız gerekir let angle: CGFloat = 45°. Ancak bir CGFloatveya herhangi bir FloatingPointtür beklediği yerde gerekli değildirCGAffineTransform(rotationAngle: 45°)
— Leo Dabus

11

Ayrıca, fron radyanları derecelere dönüştürmek için (eğer birisi buna Google'da rastlarsa):

var degrees = radians * (180.0 / M_PI)

3

Değişken adları oluştururken artık ASCII karakterleriyle sınırlı değilsiniz, bu yüzden π (alt-p) kullanarak buna ne dersiniz?

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

Örnek kullanım:

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

Global genel işlevler yazabilirsiniz:

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

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

Misal:

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

Tüm kayan türlerinizi bu şekilde genişletmek istemediğinizde

extension FloatingPoint { ... }

Neden basitçe değil return .pi * degrees / 180?
— Leo Dabus

@LeoDabus için Tolan FloatingPointtipi ve 180 Inttürü. Swift ile farklı türlerde hesaplamalar yapamazsınız.
— Tikhonov Alexander

Hatalısınız. Swift türü çıkarabilir. FloatingPoint türünü genişletiyormuşsunuz gibi tam olarak aynı şekilde davranır. 180 herhangi bir şey olabilir. Bir Int
— Leo Dabus

1
FloatingPoint, ExpressibleByIntegerLiteral ile uyumludur, bu yüzden oraya 180 yazabilirsiniz
— Leo Dabus

1
180.0, T'ye ihtiyaç duyar çünkü T'nin mutlaka bir İkili olması gerekmez. Herhangi bir kayan nokta türü olabilir. Çift 180.0
— Leo Dabus

1

Yukarıda bahsedilen @ t1ser prensibinin aynısını kullanırdım, ancak CGFloatderece için de ondalık sayıları kullanmayı kolaylaştırmak için bir uzantı oluştururum (böylece örneğin 23.4 dereceye sahip olabilirsiniz):

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

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

Bunu kullanmak da oldukça kolay olurdu (esas olarak kişisel olarak ° 😜 yazmayı bilmediğim için - siz de yapmadıysanız, btw'dir option+shift+8):

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

Veya başlatıcıyı kullanmak için:

let convertedDegrees = CGFloat(degrees: 45.3)
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.