I add a general answer to your request in case the step number changes from 0.1 to 0.01 or 0.001.
The first one is to simplify the case so that the @IBAction can be called without confusing.
@IBAction func oversStepper(_ sender: UIStepper) {
let myValue : MyFloat = MyFloat(Float(sender.value))
sender.value = myValue.value
displayOversLabel.text = String(format: "%.1f", sender.value)
}
MyFloat here plays a role as a number validator. the UIStepper value can be corrected by a MyFloat object.
The next question is Float can be compared by a precision control way. In other words, the accuracy of Float number can be achieved by limiting the abs of different between a number and an actual number, such as abs(a-b) < precision (1e-4), so we know they are close enough.
Based on this assumption, construct a MyFloat and run testCases as following:
let presicion: Float = 1e-4
struct MyFloat {
private var val: Float = 0
init(_ v: Float){value = v}
var value : Float {
get{ return val}
set{
let ro = newValue.rounded()
let ground = newValue.rounded(FloatingPointRoundingRule.towardZero)
val = (trunc(newValue) == round(newValue) || abs((ground + ro) / 2.0 - newValue) < presicion ) ? newValue :
(abs(val - ro) < presicion) ? (ground + ro) / 2.0 : ro
}
}
static func +=(left: inout MyFloat, right: Float){
left.value = left.value + right
}
static func -=(left: inout MyFloat, right: Float){
left.value = left.value - right
}
}
//naive testCases
var myFloat = MyFloat(10.0)
myFloat += 0.1; assert(abs( myFloat.value - 10.1) < presicion);
myFloat += 0.1; assert(abs( myFloat.value - 10.2) < presicion);
myFloat += 0.1; assert(abs( myFloat.value - 10.3) < presicion);
myFloat += 0.1; assert(abs( myFloat.value - 10.4) < presicion);
myFloat += 0.1; assert(abs( myFloat.value - 10.5) < presicion);
myFloat += 0.1; assert(abs( myFloat.value - 11.0) < presicion);
myFloat += 0.1; assert(abs( myFloat.value - 11.1) < presicion);
myFloat += 0.1; assert(abs( myFloat.value - 11.2) < presicion);
myFloat += 0.1; assert(abs( myFloat.value - 11.3) < presicion);
myFloat += 0.1; assert(abs( myFloat.value - 11.4) < presicion);
myFloat += 0.1; assert(abs( myFloat.value - 11.5) < presicion);
myFloat += 0.1; assert(abs( myFloat.value - 12.0) < presicion);
myFloat += 0.1; assert(abs( myFloat.value - 12.1) < presicion);
myFloat += 0.1; assert(abs( myFloat.value - 12.2) < presicion);
myFloat -= 0.1; assert(abs( myFloat.value - 12.1) < presicion);
myFloat -= 0.1; assert(abs( myFloat.value - 12.0) < presicion);
myFloat -= 0.1; assert(abs( myFloat.value - 11.5) < presicion);
myFloat -= 0.1; assert(abs( myFloat.value - 11.4) < presicion);
myFloat -= 0.1; assert(abs( myFloat.value - 11.3) < presicion);
myFloat -= 0.1; assert(abs( myFloat.value - 11.2) < presicion);
myFloat -= 0.1; assert(abs( myFloat.value - 11.1) < presicion);
myFloat -= 0.1; assert(abs( myFloat.value - 11.0) < presicion);
myFloat -= 0.1; assert(abs( myFloat.value - 10.5) < presicion);
myFloat -= 0.1; assert(abs( myFloat.value - 10.4) < presicion);
myFloat -= 0.1; assert(abs( myFloat.value - 10.3) < presicion);
myFloat -= 0.1; assert(abs( myFloat.value - 10.2) < presicion);
The advantage of this approach is the step value can be much more precise as like 0.001 without any new code, and only one parameter needs care: precision. (for example, precision = 1e-6 will give a wrong answer in this case.)
BTW, this answer also applies to negative values by masking the range of (-1 + n,-0.5 + n), n<=0.