众所周知,当用精确的数字(如金钱)计算时,最好使用NSDecimalNumber,而不是基本的floatdouble。然后,我们有取整选项:

public enum RoundingMode : UInt {

    case plain // Round up on a tie
    case down // Always down == truncate
    case up // Always up
    case bankers // on a tie round so last digit is even
}

问题:
如何对此.plain执行舍入半降(与NSDecimalNumber相反,在平局上舍入)?
我原来的问题(你当然可以跳过这一节)
设置舍入选项(可以更改):向上、向下、半向上
我用这个公式计算avar pT = price include tax中的var p = price exclude tax
pT = roundingWithOption(p * tax)

pT是显示的unitPrice(必须包含tax或business goes to jail lol),人们可以自定义它=>我必须计算价格不含税,通过还原过程
p = roundingWithReverseOption(pT2 / tax)

然后我可以将这个price exclude tax保存到服务器,稍后再取回。我们只保存p是因为税可能会改变,我们可以从其他地方获得税,如果税改变,pT可能会不同。
如果没有变化(四舍五入、税…),则save and continue过程前后的数字应该相同。
当选项是.up.down时很简单,但我不知道如何处理.plain
或者你能提供一个更好的解决方案来计算来自定制价格的priceExcludeTax?当应用折扣和数量时会更复杂,所以我先问一个简单的问题。

最佳答案

您可以尝试使用此函数,其中scale定义所需的精度:

func roundSubPlain(_ num: NSDecimalNumber, scale: Int = 0) -> NSDecimalNumber {
    let precision = (1 / pow(10, scale + 2))
    let adjustedDecimalNumber = NSDecimalNumber(decimal: num.decimalValue - precision)
    let handler = NSDecimalNumberHandler(roundingMode: .plain, scale: Int16(scale), raiseOnExactness: true, raiseOnOverflow: true, raiseOnUnderflow: true, raiseOnDivideByZero: true)
    let roundedNum = adjustedDecimalNumber.rounding(accordingToBehavior: handler)

    return roundedNum
}

所以如果你尝试:
let num1 = NSDecimalNumber(decimal: 5.5)
let num2 = NSDecimalNumber(decimal: 6.25)

您将拥有:
let subNum1 = roundSubPlain(num1) // 5
let subNum2 = roundSubPlain(num1, scale: 1) // 6.2

如果你想让银行家们也做同样的工作,你可以用这样的方法:
func roundOdd(_ num: NSDecimalNumber, scale: Int = 0) -> NSDecimalNumber {
    let handler = NSDecimalNumberHandler(roundingMode: .bankers, scale: Int16(scale), raiseOnExactness: true, raiseOnOverflow: true, raiseOnUnderflow: true, raiseOnDivideByZero: true)
    let roundedNum = num.rounding(accordingToBehavior: handler)

    let diff = num.decimalValue - roundedNum.decimalValue
    let gap = (1 / pow(10, scale))

    if abs(diff / gap) == 0.5 {
        let adjust: Decimal = diff > 0 ? 1 : -1
        return NSDecimalNumber(decimal: roundedNum.decimalValue + adjust * gap)
    } else {
        return roundedNum
    }
}

这当然可以改进,但它是有效的:)
let num = NSDecimalNumber(decimal: 6.15)
let odd = roundOdd(num, scale: 1) // 6.1

关于swift - 四舍五入NSDecimalNumber HalfDown,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/49402306/

10-11 17:46