'How to plus or minus a double value by step in swift?

Let's assume we have a double value 0.000025900,

Expect: Calling minus() returns 0.000025899 and plus() returns 0.000025901

What I've tried so far:

func plus(text: String) -> String {
    let reminder = text.components(separatedBy: ".").last ?? "0"
    let integer = text.components(separatedBy: ".").first ?? "0"
    let str = (Int(reminder) ?? 0) + 1
    return String(integer) + "." + String(str)
}

func minus(text: String) -> String {
    let reminder = text.components(separatedBy: ".").last ?? "0"
    let integer = text.components(separatedBy: ".").first ?? "0"
    let str = max(0, (Int(reminder) ?? 0) - 1)
    return String(integer) + "." + String(str)
}

These two functions only work well while there is no 0s between . and truncating part likes 0.25900.



Solution 1:[1]

Your code is good for the first part, which is separating the integer from the decimal part. To keep the decimal part properly formatted when the function returns, you need to store the number of characters in a variable, and use it to transform it back.

Here's the code for the plus() function:

    func plus(text: String) -> String {
        let remainder = text.components(separatedBy: ".").last ?? "0"
        let integer = text.components(separatedBy: ".").first ?? "0"
        
        // Store the number of characters of the remainder
        let length = remainder.count
        
        let newRemainder = (Double(remainder) ?? 0.0) + 1.0
        
        // Turn the "integer remainder" into a Double using the number of characters to calculate the denominator
        let result = (Double(integer) ?? 0.0) + newRemainder / pow(10, Double(length))
        
        // Format the result using the number of characters as the precision
        return String(result.formatted(.number.precision(.fractionLength(length))))
    }

I still need to figure out the code for the minus() function... :)

Solution 2:[2]

There could be many solutions to this problem. Here is my solution. There could be some errors. I think it could help you with how to perform a minus function.

func plus(text: String) -> String {
    guard text.contains(".")  else {
        // value = 2 return value should be 2.1
        return text + ".1"
    }
    let intialValueAfterDecimalPoint = text.components(separatedBy: ".").last ?? "0"
    // Make .00 to .100 / .9001 to .19001 if at some point only 0's after decimal point for making easy calculation
    let modifiedIntialValueAfterDecimalPoint = "1" + intialValueAfterDecimalPoint
    let intialIntegerValue = text.components(separatedBy: ".").first ?? "0"
    let modifiedIntitialValueAfterDecimalPoint = Int(modifiedIntialValueAfterDecimalPoint) ?? 0
    //Need to add carry value to initial interger value if there is a carry value in decimalValue addition
    // For example .99 + 1 = 1.00
    let firstIndexValueWithCarryValue = calculateCarryValue(text: String(modifiedIntitialValueAfterDecimalPoint + 1))
    
    if firstIndexValueWithCarryValue == 2 {
        let finalValueAfterDecimalPoint = String(modifiedIntitialValueAfterDecimalPoint + 1).dropFirst()
        return String((Int(intialIntegerValue) ?? 0) + 1) + "." + finalValueAfterDecimalPoint
    } else {
        return String(intialIntegerValue) + "." + String(modifiedIntitialValueAfterDecimalPoint + 1).dropFirst()
    }
}

func calculateCarryValue(text: String) -> Int {
    let revString = String(text.reversed())
    let carryValue = (Int(revString) ?? 0) % 10
    return  carryValue
}

func minus(text: String) -> String {
    guard text.contains(".")  else {
        // value = 2 return value should be 1.9
        let intValue = Int(text) ?? 0
        if intValue == 0 {
            return "-1"
        } else  {
            return String(intValue - 1) + ".9"
        }
    }
    let intialValueAfterDecimalPoint = text.components(separatedBy: ".").last ?? "0"
    // Make .00 to .100 / .9001 to .19001 if at some point only 0's after decimal point for making easy calculation
    let modifiedIntialValueAfterDecimalPoint = "1" + intialValueAfterDecimalPoint
    let intialIntegerValue = text.components(separatedBy: ".").first ?? "0"
    let modifiedIntitialValueAfterDecimalPoint = Int(modifiedIntialValueAfterDecimalPoint) ?? 0
    //Need to minus carry value to initial interger value if there is a carry value in decimalValue subtraction
    // For example 1.000 - 1 = 0.999
    let firstIndexValueWithMinusCarryValue = String(modifiedIntitialValueAfterDecimalPoint - 1)

    let negativeCarryValue = firstIndexValueWithMinusCarryValue.count < modifiedIntialValueAfterDecimalPoint.count ? 1 : 0
    
    if negativeCarryValue == 1 {
        let finalValueAfterDecimalPoint = String(modifiedIntitialValueAfterDecimalPoint - 1)
        return String((Int(intialIntegerValue) ?? 0) - 1) + "." + finalValueAfterDecimalPoint
    } else {
        return String(intialIntegerValue) + "." + String(modifiedIntitialValueAfterDecimalPoint - 1).dropFirst()
    }
}

print(plus(text: "1.00"))
print(plus(text: "0.9999"))
print(minus(text: "1.00"))
print(minus(text: "0.9999"))

Solution 3:[3]

Just use Decimal's nextUp and nextDown.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 HunterLion
Solution 2 Md Abul Kashem
Solution 3 Zigii Wong