Search code examples
iosswiftintuistepper

How to round each .5 number up to whole value when incrementing by 0.1


I'm building a cricket app. I want the number to increase by .1 but once it reaches .5 and I hit plus again, I want it to round up to the whole value.

eg. 2.1, 2.2, 2.3, 2.4, 2.5 then jumps to 3.0 (then starts over again 3.1, 3.2, 3.3 etc.)

My stepper currently goes up and down by .1 but it includes decimals (.6, .7, .8 & .9)

Everytime it hit's .5 of a number I need it to round up. Same when subtracting.

Here's my code:

var oversFloat: Float = 0.0

@IBOutlet weak var displayOversLabel: UILabel!
@IBAction func OversStepper(_ sender: UIStepper) {
    let oversValue = Float(sender.value)
    displayOversLabel.text = String(oversValue)

enter image description here


Solution

  • Floating point numbers are troublesome. You should really never test a float point number for equality with another value. In your case 0.1 cannot be represented exactly with a floating point number, so increasing by 0.1 introduces increasing error. So your number might end in 0.499999999 when you were expecting 0.5.

    In your case, you can easily avoid this issue by using whole numbers in your stepper. Modify your stepper to step by 1 instead of by 0.1 and multiply your minimum and maximum values by 10. Then, when you use your stepper value to update your label, divide the stepper value by 10.

    For jumping from 88.5 to 89.0 which incrementing, and from 89.0 to 88.5 when decrementing, check for the one's digit being 6 or 9 and then increment/decrement your stepper value by 4:

    @IBAction func oversStepper(_ sender: UIStepper) {
        let value = Int(sender.value)
        let remainder = value % 10
        if remainder == 6 {
            sender.value = Double(value + 4)
        } else if remainder == 9 {
            sender.value = Double(value - 4)
        }
        displayOversLabel.text = String(format: "%.1f", sender.value / 10)
    }
    

    By stepping with whole values, no error will be introduced.