0

I have a UISlider that has min value of 0 and a max value of 1.

When it stops it can be any number such as

3.2990444444444442

In this situation I want to increase the last number to a 3 as in

3.2990444444444443

But since it's a slider, I'll never know the exact number until it stops, so the number might be

0.0019881635 at which I would want to increase to 0.0019881636 or 0.999 to 1.0

How can I do this?

If it's not clear what I want to do, no matter what the last digit is in the slider decimal value, I need to increase it by 1

A lot of the answers that I came across are in another language, not Swift

Lance Samaria
  • 17,576
  • 18
  • 108
  • 256
  • Re “min value of 0 and a max value of 1” and “it can be any number such as 3.2990444444444442”: I detect a problem in your problem. – Eric Postpischil Mar 24 '22 at 22:53
  • 1
    The Swift `Float` type uses two as a base. It does not have any decimal digits. The decimal digits you see display are the result of a conversion that rounds the actual `Float` value to a decimal numeral. Those digits are not the actual value of the `Float`. So if you see “3.299044” for a `Float`, that last “4” is not the actual last digit in the number. There is not a good definition for the “last digit” of a `Float` value. What are you trying to do and why do you need to do this? – Eric Postpischil Mar 24 '22 at 22:57
  • The problem is you said the minimum value is 0 and the maximum value is 1 but a possible value is 3.299… That value, 3.299…, is outside the allowed range. So something is wrong. – Eric Postpischil Mar 24 '22 at 22:58
  • @EricPostpischil I'm using it for an AVPlayer. When it stops I need to record the value that it started and stopped at. But if the user starts where it was stopped then the next record has the same start value as the previous records stop value. What I thought of was when it stops, just change the seek time by the 1 digit, that way the next record won't have the same start as the previous record's stop. Does that make sense to you. Basically I'm increasing the player's seekTime by the 1 value – Lance Samaria Mar 24 '22 at 23:01
  • I see the issue, I explained it wrong. The slider value's max is 1, it won't ever go beyond that. The number 3.299 won't ever get hit because the slider will always stop at 1. I'm only looking for number in between 0 and 1. – Lance Samaria Mar 24 '22 at 23:03
  • Your explanation is unclear. If the point where the previous record stops and the point where the next record begins are the same point, so what? If the user sets the slider to that point, just play forward. That plays the next record. It is not clear why any sort of adjustment is needed or why the two points cannot have the same coordinate. In any case, Swift has a function/method for adjusting a `Float` upward by the smallest possible amount: `nextUp`. It returns the next representable value greater than the current value. – Eric Postpischil Mar 24 '22 at 23:06
  • I'd have to explain in more detail, it has to do more with the actual project. But I never knew about the `nextUp` function. Can you post it as answer, If it works as I need it I'll upvote it. – Lance Samaria Mar 24 '22 at 23:07
  • The answer you accepted (currently) returns 0.2 for input of 0.1. Is that what you want? – Eric Postpischil Mar 24 '22 at 23:09
  • @EricPostpischil nextUp will do the same. Note that at 0.9 it will go to 1.0 and then It would go to 2 not 1.1. Note that I am talking about Decimal not Double which doesn't behave the same way as Decimal. – Leo Dabus Mar 24 '22 at 23:14
  • @LeoDabus I just tested it several times. When it hit **1.0** `.nextUp` went to **1.0000001** whereas the accepted answer went to **2.0**. On a side note, it turns out I needed both answers because quite a few times one would go up and the other would stay equal to the slider.value. I have no idea why 1 would go up and the other would stay equal. For clarity, sometimes both `.nextUp` and `increaseLast()` wouldn't increase. – Lance Samaria Mar 25 '22 at 02:39
  • 1
    @LanceSamaria You need to use `Decimal` type not floating point types`Float or Double`. So I would get the FloatingPoint string, use it to initialize a decimal object, go to the next up and then get the its floating point value. To convert from `Decimal` to `Double` you need to cast it to `NSDecimalNumber` – Leo Dabus Mar 25 '22 at 03:02
  • 1
    @LeoDabus Ahhhhhhh, ok, you mentioned that earlier but you didn't say why. Now I get it, you foresaw these issues. Ok, I'll follow your answer that uses Decimals. Thanks for you help! – Lance Samaria Mar 25 '22 at 03:16

2 Answers2

1

nextUp returns the next Float value greater than the given value.

Note that if the slider is set to 1, it will return a value greater than 1, so you may want to clamp that value.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
0

Consider this solution:

extension Float {
func decimalCount() -> Int {
    if self == Float(Int(self)) {
        return 0
    }

    let integerString = String(Int(self))
    let doubleString = String(self)
    let decimalCount = doubleString.count - integerString.count - 1

    return decimalCount
}

mutating func increaseLast(){
    let powerfactor = pow(10, Float(decimalCount()))
    self = (self * powerfactor + 1) / powerfactor
    
 }
}

I didn´t test this thoroughly but it should work. Got the function decimalcount from this so answer

Usage example:

let array: [Float] = [0.999, 0.0004, 0.004, 0.009]

array.forEach{
  var a = $0
  a.increaseLast()
  print($0)
  print(a)
}

prints:

0.999
1.0
0.0004
0.0005
0.004
0.005
0.009
0.01
burnsi
  • 6,194
  • 13
  • 17
  • 27