1

I have one float number initialized from a json server response like 65.788, 43.77, 89, 58.86985 … I need print this with only two decimals digits. But without any round.

My problem is that while I format my float number to add only two digits, this format is applying an automatic round of the last digit.

let weight = 65.788
let string = String(format: "%.2f", weight). // ->  65.79

I’m getting 65.79 but I need get 65.78

How could get from the number of json response only two digits without rounding? Thanks!

user3745888
  • 6,143
  • 15
  • 48
  • 97
  • 1
    Use a NumberFormatter and specify the roundingMode – this must have been asked and answered before ... – Martin R Jun 03 '19 at 12:25
  • 2
    This might help -> https://stackoverflow.com/questions/31542199/swift-string-from-float-without-rounding-the-values – Cedan Misquith Jun 03 '19 at 12:27
  • And between ceiling, floor, down, up, halfEven, halfDown, halfUp what is the RoundingMode to not apply a rounding?? @MartinR thanks! – user3745888 Jun 03 '19 at 12:30
  • @user3745888 There must be rounding. The number is represented in binary and you want decimal representation, it's not as simple as truncating some digits. You might get a decent solution by using `String(format: "%.2f", weight >= 0 ? weight - 0.005 : weight + 0.005)` but the real solution is to use `NumberFormatter` and choosing the rounding mode correctly (probably `.down`). – Sulthan Jun 03 '19 at 12:35
  • You are rounding. You are either rounding towards zero or rounding down, depending on what behaviour you want with negative numbers. – James Snook Jun 03 '19 at 12:39
  • 1
    Have a look at https://stackoverflow.com/a/27705739. – Martin R Jun 03 '19 at 12:48
  • If you will convert it into `Double` it will round anyway. You need to do it with `String` variable. – TheTiger Jun 03 '19 at 12:53

1 Answers1

12

Use NumberFormatter with .roundingMode = .down

    let nf = NumberFormatter()
    nf.roundingMode = .down

    // max of 2 decimal places (e.g. 1.23, 1.2, 1)
    nf.maximumFractionDigits = 2

    // starting with Strings
    ["65.788", "1.2", "1.9", "1"].forEach { s in
        let n = Float(s)
        let t = nf.string(for: n)
        print("[" + t! + "]")
    }

    // starting with Numbers
    [65.788, 1.2, 1.9, 1].forEach { n in
        let t = nf.string(for: n)
        print("[" + t! + "]")
    }

    // if you want exactly 2 decimal places (e.g. 1.23, 1.20, 1.00)
    nf.minimumFractionDigits = 2

    // starting with Strings
    ["65.788", "1.2", "1.9", "1"].forEach { s in
        let n = Float(s)
        let t = nf.string(for: n)
        print("[" + t! + "]")
    }

    // starting with Numbers
    [65.788, 1.2, 1.9, 1].forEach { n in
        let t = nf.string(for: n)
        print("[" + t! + "]")
    }

Output:

[65.78]
[1.2]
[1.9]
[1]
[65.78]
[1.2]
[1.9]
[1]
[65.78]
[1.20]
[1.90]
[1.00]
[65.78]
[1.20]
[1.90]
[1.00]

Obviously, you want to use error checking to make sure your original strings can be converted to numbers, etc...

DonMag
  • 69,424
  • 5
  • 50
  • 86