How to represent magnitude for mass in Swift?

后端 未结 3 938
甜味超标
甜味超标 2021-01-06 13:31
// SI units
enum Magnitude : Measurement {
    case Milli = Measurement(-3, \"ml\")
    case Centi = Measurement(-2, \"cl\")
    case Desi = Measurement(-1, \"dl\")
         


        
相关标签:
3条回答
  • 2021-01-06 14:07

    Depending on what you need, maybe you can combine an enumeration of SI unit scales and the example in the Computed Properties section of Apple Swift Programming Guide. In this simplistic scheme all of input measurements would be stored in the same units (grams in this example). Then you would convert to whatever units you needed in the output.

    It is very readable.

    enum SI {
        case kg
        case hg
        case dag
        case g
        case dg
        case cg
        case mg
    
        var scale: Double {
            switch self {
            case kg:  return    0.001
            case hg:  return    0.01
            case dag: return    0.1
            case g:   return    1.0
            case dg:  return   10.0
            case cg:  return  100.0
            case mg:  return 1000.0
            }
        }
    }
    
    extension Double {
        var kg:  Double {return self * 1000.0}
        var hg:  Double {return self *  100.0}
        var dag: Double {return self *   10.0}
        var g:   Double {return self}
        var dg:  Double {return self *    0.1}
        var cg:  Double {return self *    0.01}
        var mg:  Double {return self *    0.001}
    
        func convertTo(si: SI) ->  Double {return self * si.scale}
    }
    

    Example:

    enter image description here

    0 讨论(0)
  • 2021-01-06 14:08

    Did you consider using a dictionary? For example:

    let magnitudes: [String: Double] = [
        "ml": -3,
        "cl": -2,
        "dl": -1,
        "g": 0,
        "kg": 3
    
    ]
    
    // list all units:
    println(", ".join(magnitudes.keys)) // kg, g, ml, cl, dl
    
    
    // convert
    func convert(from: String, to: String, value: Double) -> Double{
        let mag1 = __exp10(magnitudes[from]!)
        let mag2 = __exp10(magnitudes[to]!)
        return value * mag1 / mag2
    }
    
    
    let result = convert("dl", "ml", 3.0)
    println(result) // 300.0
    
    0 讨论(0)
  • 2021-01-06 14:10

    If you want to be able to specify the unit of the mass with a String perhaps you could use String to represent the shorthand name and variables to give you more information about the unit, such as magnitude. Here's an example:

    1. MassUnit

    enum MassUnit: String {
        case Milligrams = "mg"
        case Grams      = "g"
        case Kilos      = "kg"
        case Tons       = "t"
    
        var magnitude: Int {
            let mag: Int
    
            switch self {
                case .Milligrams: mag = -3
                case .Grams     : mag =  0
                case .Kilos     : mag =  3
                case .Tons      : mag =  6
            }
    
            return mag
        }
    
    
        static func ordersOfMagnitudeFrom(unit1: MassUnit, to unit2: MassUnit) -> Int {
            return unit1.magnitude - unit2.magnitude
        }
    }
    
    extension MassUnit: Printable {
        var description: String {
            return self.rawValue
        }
    }
    

    2. Then, for storing actual masses you could use a Struct, which could also handle the conversions. For example:

    struct Mass {
        var value : Double
        var unit  : MassUnit
    
        static func convertMass(mass: Mass, toUnit unit: MassUnit) -> Mass {
            let ordersOfMagnitude = MassUnit.ordersOfMagnitudeFrom(mass.unit, to: unit)
    
            let multipler = pow(10.0, Double(ordersOfMagnitude))
    
            return Mass(value: mass.value * multipler, unit: unit)
        }
    
        //  Returns an optional Mass because we can't know for sure 
        //  unitString will represent a MassUnit.
        static func convertMass(mass: Mass, toUnit unitString: String) -> Mass? {
            if let unit = MassUnit(rawValue: unitString) {
                return convertMass(mass, toUnit: unit)
            }
    
            return nil
        }
    }
    
    extension Mass {
        init?(value: Double, _ unitString: String) {
            if let unit = MassUnit(rawValue: unitString) {
                self = Mass(value: value, unit: unit)
            } else {
                return nil
            }
        }
    }
    
    extension Mass : Printable {
        var description: String {
            return "\(value) \(unit)"
        }
    }
    

    3. Then you can use the masses and units:

    if let mass = Mass(value: 1, "kg"),
       let convertedMass = Mass.convertMass(mass, toUnit: "g") {
    
        println("\(mass) converted to \(MassUnit.Grams) equals \(convertedMass)")
    
        // Prints: 1.0 kg converted to g equals 1000.0 g
    }
    

    However if you use a unitString that isn't convertible to a MassUnit (either when creating or converting) nil will be returned. For example:

    let mass = Mass(value: 1, "NotAUnit") // nil
    
    0 讨论(0)
提交回复
热议问题