2014-11-04 12 views
7

Nach The Swift Programming Language sollte ich in der Lage sein, eine Swift-Enumeration mit Rohwerten von "Strings, Characters oder beliebigen Integer- oder Floating- Punktnummertypen ". Aber wenn ich versuche:"Raw-Wert für enum case ist nicht eindeutig" für Swift-Enum mit Float-Rohwerten

enum BatteryVoltage: Float { 
    case v3v7 = 3.7 
    case v5v0 = 5.0 
    case v7v4 = 7.4 
    case v11v1 = 11.1 
    case v12v0 = 12.0 
} 

... ich einen Kompilierungsfehler erhalten:

Raw value for enum case is not unique 

auf der v7v4 Linie. Es kompiliert gut mit dem auskommentierten. Aber ach, es sieht einzigartig für mich aus. Wenn ich den Wert 7,41, oder 7.3 oder etwas anderes mache, kompiliert es sich gut. Was ist los? Schneller Fehler?

+1

Das sieht definitiv wie ein Fehler aus. Es scheint zu passieren, wenn ein Enum-Wert genau gleich "2 mal ein anderer Enum-Wert" ist (aber keine ganze Zahl). –

+0

Sie wissen was, Sie haben Recht. Beantworte deinen Kommentar und ich akzeptiere. (Und file ein Radar. Seufz.) –

+0

Ich denke, dass dies mit der binären Darstellung eines Floats verbunden werden könnte. Vielleicht schneidet der Gleichheitsvergleich für Enums einige Bits ab. – Sulthan

Antwort

6

Es sagt auf jeden Fall Ihnen kann, aber nicht verwenden Gleitkommawerte (und vor allem Float), wo Sie brauchen werden Gleichheit vergleichen - die Präzision einfach nicht gut genug sein, ist garantiert. Und verwenden Sie immer Double, wenn Sie aus Kompatibilitätsgründen unbedingt einen Float verwenden müssen.

In diesem Fall scheint es Probleme zu haben, weil (a) der dritte Fall 2x der erste Fall ist, und (b) ein anderer Faktor, den ich nicht kenne. Mit 3.3/6.6, 3.4/6.8 und 3.6/7.2 gab mir auch das Problem, aber 3.5/7.0 nicht. Jedoch könnte ich es bekommen, indem ich den letzten Fall zu 22.2 (2x 11.1) ändere.

Hier ist eine Abhilfe - verwenden, um eine typische Int -basierte Aufzählung und bieten eine doubleValue Eigenschaft:

enum BatteryVoltage: Int { 
    case v3v7 
    case v5v0 
    case v7v4 
    case v11v1 
    case v12v0 

    var doubleValue: Double { 
     switch self { 
     case .v3v7: return 3.7 
     case .v5v0: return 5.0 
     case .v7v4: return 7.4 
     case .v11v1: return 11.1 
     case .v12v0: return 12.0 
     } 
    } 
} 

Es gibt einige nice additional features of enums Sie nutzen können, wenn sie sind Int -Basis.

+0

Ich gebe Ihnen dies für den Blog Post Link-Hinzufügen einer Methode zu der Enumeration, die den Int-Wert verwendet, um in ein Array von Werten zu indizieren ist eine bessere Möglichkeit zu erreichen, was ich tun wollte. –

4

(Von meinem obigen Kommentar :)

das auf jeden Fall wie ein Fehler aussieht. Es scheint zu passieren, wenn ein Enum-Wert genau gleich "2 mal ein anderer Enum-Wert" ist, aber nicht gleich einem Integer.

Allgemeiner (als @Sulthan beobachtet) der Fehler tritt auf, wenn das Verhältnis der Aufzählungswerte ist eine Zweierpotenz wie 3.7/7.4, 1.2/4.8 oder 1.1/17.6, aber nur wenn beide Werte a haben Nicht-Null-Bruchteil. So 1.5/3.0 oder 1.25/5.0 nicht verursachen einen Fehler.

+0

@Sultan: Du hast Recht, nicht nur Faktor 2 verursacht das Problem sondern auch 4, 8, 16, ... –