2016-04-09 5 views
0

Ich habe diesen Ausdruck. Es ist in Objective-C.Gleicher Ausdruck gibt verschiedene Werte in Objective-C und Swift zurück

CGFloat x1 = self.frame.size.width/2 + ((self.frame.size.width - self.borderWidth * 2 - self.graduationOffset)/2) * cos((6 * i) * (M_PI/180) - (M_PI/2)); 

Hier sind die Werte für jede Variable/Eigenschaft. Sie sind alle vom Typ CGFloat.

self.frame.size.width = 200

self.borderWidth = 3

self.graduationOffset = 10

Dieser ganze Ausdruck in einer Schleife ist, die 60-mal ausführt. Der Wert von i beginnt bei 0 und geht über zu 60. Im Codebeispiel auf, es 0.

war

Der Wert von x1 ist .

Ich konvertierte diesen Ausdruck zu Swift wie folgt.

let x1 = Double(frame.size.width/2 + ((frame.size.width - borderWidth * 2 - graduationOffset)/2)) * cos(Double((6 * i)) * (M_PI/180) - (M_PI/2)) 

Die gleichen Werte für die Variablen übergeben. Das Ergebnis ist 1.17566092718146e-14.

Ich habe versucht, es zu zerlegen und die Werte separat zu überprüfen, um dies herauszufinden. Aber das verursachte nur mehr Verwirrung. Weil ich 0 als Endergebnis bekommen habe!

Ich versuchte das gleiche in Swift und bekam unterschiedliche Ergebnisse.

let a = Double(frame.size.width/2 + ((frame.size.width - borderWidth * 2 - graduationOffset)/2)) 
print(a) // 192.0 
let b = cos(Double((6 * i)) * (M_PI/180) - (M_PI/2)) 
print(b) // 6.12323399573677e-17 
let c = a * b 
print(c) // 1.17566092718146e-14 

Ich bin den ganzen Tag gegangen, aber kann das alles nicht herausfinden. Ich denke, die Art, wie Ausdrücke ausgewertet werden, unterscheidet sich zwischen Objective-C und Swift? Ich würde jede Hilfe sehr schätzen.

+1

['NSLog' _rounds_ Ausgabe auf 6 Dezimalstellen] (http://stackoverflow.com/questions/11410791/rounding-a-float-number-in-objective-c), während' print (..) 'nur Gibt den gespeicherten Wert aus. Das '.... e-14' ist nur ein klassisches Gleitkomma-Präzisions-Problem (suche SO nach einem der zahlreichen Fragen und Antworten zur Gleitkomma-Genauigkeit). Der Wert ist im Wesentlichen "0", aber nicht gerundet, er zeigt all seinen nicht präzisen Wahnsinn. Stellen Sie sicher, dass Sie keine Gleichheitsprüfungen oder Gleichheitsprüfungen (z. B. "b> 0?") Für Fließkommazahlen durchführen. – dfri

+1

Auch Ihre erste Aussage vs. die zergliederte Aussage * sind nicht gleich. In der ersten multiplizieren Sie mit dem 'cos (...)' und addieren dann die halbe Breite. Im aufgegliederten Teil addierst du die halbe Breite und multiplizierst dann mit dem 'cos (...)' – Hamish

+1

Mit dem irreführenden Titel "Gleicher Ausdruck" nach unten. Das sind keine Äpfel und Orangen. Sie vergleichen mit zwei verschiedenen Protokollierungsmechanismen, anstatt nur im Debugger zu suchen. Und Sie verwenden zwei verschiedene Typen, 'CGFloat' gegenüber' Double' (und nicht erwähnt, ob Sie auf 32-Bit- oder 64-Bit-Geräten vergleichen). – nhgrif

Antwort

2

Lassen Sie uns teilen Sie Ihre Obj-C-Code in 3 Teile:

CGFloat x1 = frameWidth/2 + ((frameWidth - borderWidth * 2 - graduationOffset)/2) * cos((6 * i) * (M_PI/180) - (M_PI/2)); 

CGFloat part1 = frameWidth/2; 
CGFloat part2 = ((frameWidth - borderWidth * 2 - graduationOffset)/2); 
CGFloat part3 = cos((6 * i) * (M_PI/180) - (M_PI/2)); 

Ihre Obj-C-Version dann result = part1 + (part2 * part3) tun ist (ich bin sicher, Sie wissen, dass * Vorrang vor + hat), während die zusätzliche Double(...) gossenen Die Swift-Version konvertiert den Ausdruck in result = (part1 + part2) * part3. Seit part3 ist 0 für , das Ergebnis ist klar.

+3

@Isuru Bemerkenswert, dass die Aufspaltung Ihrer Logik in mehrere Zeilen nicht nur den Fehler beseitigt, sondern Ihren Code viel lesbarer und wartbarer macht. Kompakter Code * rein * wegen kompakter Code ist selten eine gute Idee. – Hamish

Verwandte Themen