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.