-1

as describe in the title, the Swift String() function does not work as I expected:

 String(format: "%.1f", 8.25)

does NOT return 8.3 as expected (rounded) but 8.2.

If I use

String(format: "%.1f", 8.251)

it return 8.3, so it does not simply cut the place(s).

Is this how it should work or are there any explanation why this happens?

I know that there is a solution like this.

round(10*8.25)/10

I would like to understand the behaviour of the String() function.

  • 1
    It rounds to the nearest number using the given precision. This is not a problem with the rounding logic being inconsistent but with floating point math and because in your first example 8.25 isn’t represented as 8.25 but something like 8.250001 or similar and then 8.3 is the correct nearest number to round to. – Joakim Danielson Aug 16 '22 at 20:32
  • Sorry, my example was in the wrong direction but it should be clear what I meant. So rather 8.249999… is nearer 8.2 than 8.3 – Joakim Danielson Aug 16 '22 at 20:40
  • `8.25` is exactly represented in floating point since `.25` is a power of 2. The real answer to your question is that given a digit of exactly 5 to round, it will choose to round up or down to an *even* number. Check out what happens when you round `2.5`, `3.5`, `4.5`, and `5.5` with "%.0f". You get `2`, `4`, `4`, `6`. – vacawama Aug 17 '22 at 00:51

1 Answers1

1

You can use NumberFormatter, where roundingMode property allows to "break even" any way you want:

let formatter = NumberFormatter()
formatter.positiveFormat = "0.#" // Add a negative format if needed
formatter.roundingMode = .halfUp // <-- this is the key
let y = formatter.string(from: 8.25) // y is 8.3

Note that it returns an Optional.

timbre timbre
  • 12,648
  • 10
  • 46
  • 77