-1

I have a basic question to convert string to number in Swift. I found a good stack overflow question that helps me convert a JSON string to a number, but I get an error when I try to add or subtract the values.

I am sure I am missing something obvious!

Phil

Error: Referencing operator function '-' on 'BinaryInteger' requires that 'NSNumber' conform to 'BinaryInteger'

func red2G()->String {
        let numberFormatter = NumberFormatter()
        
        // Prev Close
        let number1  = numberFormatter.number(from: pricesAlpha?.globalQuote.prevClose ?? "0.000")
        if let final1 = number1?.floatValue {
        print("Returned number is " + String(format: "%.2f", final1))
        }
        
        // Open
        let number2  = numberFormatter.number(from: pricesAlpha?.globalQuote.open ?? "0.000")
        if let final2 = number2?.floatValue {
        print("Returned number is " + String(format: "%.2f", final2))
        }
        
        // Price
        let number3  = numberFormatter.number(from: pricesAlpha?.globalQuote.price ?? "0.000")
        if let final3 = number3?.floatValue {
        print("Returned number is " + String(format: "%.2f", final3))
        }
        
        return String(number3-number2)
     }

I simplified the function based on the proposed answer:

    func load(symbolName:String) {
        self.symbolName = symbolName
    }
    
    func red2G()->String {
        let numberFormatter = NumberFormatter()
        
        // Prev Close
        let prevClose  = numberFormatter.number(from: pricesAlpha?.globalQuote.prevClose ?? "0.000")?.floatValue
        
        // Open
        let openPrice  = numberFormatter.number(from: pricesAlpha?.globalQuote.open ?? "0.000")?.floatValue
        
        // Price
        let currentPrice  = numberFormatter.number(from: pricesAlpha?.globalQuote.price ?? "0.000")?.floatValue
        
        return String((openPrice ?? 0.00) - (prevClose ?? 0.00) - (currentPrice ?? 0.00))
}

The values are based on this JSON Dictionary

struct GlobalQuote: Codable {
    let globalQuote: PriceAlpha
    
    enum CodingKeys : String, CodingKey {
        case globalQuote = "Global Quote"
    }
}

struct PriceAlpha: Codable {
    let symbol: String
    let open: String
    let high: String
    let low: String
    let price: String
    let volume: String
    let tradingDay: String
    let prevClose: String
    let change: String
    let pctChange: String
    
    enum CodingKeys : String, CodingKey {
        case symbol = "01. symbol"
        case open = "02. open"
        case high = "03. high"
        case low = "04. low"
        case price = "05. price"
        case volume = "06. volume"
        case tradingDay = "07. latest trading day"
        case prevClose = "08. previous close"
        case change = "09. change"
        case pctChange = "10. change percent"
    }
}

  • Can you post your JSON string? – Leo Dabus Dec 20 '20 at 00:28
  • "Error: Referencing operator function" At what line? – El Tomato Dec 20 '20 at 00:32
  • That post will return a `String` not a `Double` or `Float`. if you just want to convert `String` to `Double` just use `Double(yourString)` – Leo Dabus Dec 20 '20 at 00:40
  • Hi Leo, I tried the Double() as you suggested, it works! However, I still cannot perform basic math because a new error: Value of optional type 'Double?' must be unwrapped to a value of type 'Double'". Example: `let currentPrice = Double(pricesAlpha?.globalQuote.price ?? "0.00")`. The error occurs on this math: `return String(openPrice - prevClose)` – TraderPhilDE Dec 21 '20 at 22:30
  • Update: using guard let and else closure, I was able to solve my issue. – TraderPhilDE Dec 21 '20 at 22:40

1 Answers1

0

NSNumber is a object wrapper around an actual integer or float or whatever. You see in your code where you call floatValue? That gets an actual number that you can do math with. Keep final3 and final2 around outside of their if statements and do the math on that.

That said, you should almost certainly implement custom decoding and encoding in PriceAlpha so that the struct already contains values in the correct semantic type (e.g. Float) instead of String. But for financial information, you’ll actually want Decimal, not Float.

Donovan Voss
  • 1,450
  • 13
  • 12
  • Thanks for hint, I will move the final2 and final3 outside the if statement. I would also LOVE to convert the prices to float or decimal at decode time, it seems to be super complicated based on the examples I found on the stack overflow! – TraderPhilDE Dec 20 '20 at 21:02
  • Unfortunately, I receive a new error based on the simplified function I posted above. Error: Value of optional type 'Float?' must be unwrapped to a value of type 'Float'. I just want to do basic math on the prices :( – TraderPhilDE Dec 20 '20 at 21:27