Как округлить каждое число .5 до целого значения при увеличении на 0,1 - PullRequest
0 голосов
/ 16 декабря 2018

Я создаю приложение для игры в крикет.Я хочу, чтобы число увеличилось на .1, но как только оно достигнет .5 и я снова нажму плюс, я хочу, чтобы оно округлилось до целого значения.

например.2.1, 2.2, 2.3, 2.4, 2.5, затем переходит на 3.0 (затем начинается снова 3.1, 3.2, 3.3 и т..7, .8 & .9)

Каждый раз, когда он достигает 0,5 от числа, мне нужно, чтобы оно округлилось.То же самое при вычитании.

Вот мой код:

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

Ответы [ 2 ]

0 голосов
/ 17 декабря 2018

Я добавляю общий ответ на ваш запрос в случае изменения номера шага с 0,1 на 0,01 или 0,001.

Первый - упростить кейс, чтобы можно было вызывать @IBAction без путаницы.

      @IBAction func oversStepper(_ sender: UIStepper) {
        let myValue : MyFloat = MyFloat(Float(sender.value))
        sender.value = myValue.value

        displayOversLabel.text = String(format: "%.1f", sender.value)
    }

MyFloat здесь играет роль валидатора чисел.значение UIStepper может быть исправлено объектом MyFloat.

Следующий вопрос - Float можно сравнить с помощью метода точного управления.Другими словами, точность числа с плавающей запятой может быть достигнута путем ограничения абсолютного разности между числом и фактическим числом, таким как abs (ab) <точность (1e-4), поэтому мы знаем, что они достаточно близки. </p>

Исходя из этого предположения, создайте MyFloat и запустите testCases следующим образом:

    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);

Преимущество этого подхода заключается в том, что значение шага может быть гораздо более точным, как 0,001 без какого-либо нового кода, итолько один параметр требует внимания: точность.(например, точность = 1e-6 даст неправильный ответ в этом случае.)

Кстати, этот ответ также применяется к отрицательным значениям, маскируя диапазон (-1 + n, -0,5 + n), n <= 0. </p>

0 голосов
/ 16 декабря 2018

Числа с плавающей запятой хлопотно .Вы действительно никогда не должны проверять число с плавающей точкой на равенство с другим значением.В вашем случае 0.1 не может быть точно представлено числом с плавающей запятой, поэтому увеличение на 0.1 приводит к увеличению ошибки.Таким образом, ваш номер может заканчиваться 0.499999999, когда вы ожидали 0.5.

. В вашем случае вы легко можете избежать этой проблемы, используя целые числа в своем степпере.Измените шаговый шаг на 1 вместо 0.1 и умножьте минимальное и максимальное значения на 10.Затем, когда вы используете значение шага для обновления метки, разделите значение шага на 10.

Для перехода с 88.5 до 89.0 с увеличением и с 89.0 до 88.5при уменьшении проверьте, что цифра единицы равна 6 или 9, а затем увеличьте / уменьшите значение вашего шагового регулятора на 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)
}

Шагая с целыми значениями, ошибок не будет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...