NumberFormatter的generateDecimalNumbers不起作用

时间:2017-04-21 09:16:44

标签: swift numbers decimal

我的功能是将字符串转换为十进制

func getDecimalFromString(_ strValue: String) -> NSDecimalNumber {
    let formatter = NumberFormatter()
    formatter.maximumFractionDigits = 1
    formatter.generatesDecimalNumbers = true
    return formatter.number(from: strValue) as? NSDecimalNumber ?? 0
}

但它没有按照预期运作。有时它会像

一样回归
Optional(8.300000000000001)
Optional(8.199999999999999)

而不是8.3或8.2。在字符串中,我的值类似于“8.3”或“8.2”,但转换后的十进制数不符合我的要求。我犯错的任何建议?

2 个答案:

答案 0 :(得分:4)

这似乎是一个错误,比较

即使<?xml version="1.0" encoding="utf-8"?> <android.support.v4.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior" tools:context="com.mediasaturn.productlistpoc.activities.MainActivity" tools:showIn="@layout/activity_main"> <fragment android:name="com.productlistpoc.recyclerview.RecyclerViewFragment" android:id="@+id/fragment_recycler" android:layout_width="match_parent" android:layout_height="match_parent" tools:layout="@layout/fragment_recycler" /> </android.support.v4.widget.NestedScrollView> 设置为generatesDecimalNumbers,格式化程序也是如此 在内部生成二进制浮点数,但不能 精确地表示像true这样的小数部分。

另请注意(与文档相反),当解析字符串时,8.2属性无效 分数。

有一个简单的解决方案:使用

maximumFractionDigits

相反,取决于字符串是否已本地化。

或使用Swift 3 NSDecimalNumber(string: strValue) // or NSDecimalNumber(string: strValue, locale: Locale.current) 类型:

Decimal

示例:

Decimal(string: strValue) // or
Decimal(string: strValue, locale: .current)

答案 1 :(得分:1)

我可能倾向于只使用 Decimal(string:locale:),但如果您想使用 NumberFormatter,您只需手动舍入即可。

func getDecimalFromString(_ string: String) -> NSDecimalNumber {
    let formatter = NumberFormatter()
    formatter.generatesDecimalNumbers = true
    let value = formatter.number(from: string) as? NSDecimalNumber ?? 0
    return value.rounding(accordingToBehavior: RoundingBehavior(scale: 1))
}

或者如果您想返回一个 Decimal

func getDecimalFromString(_ string: String) -> Decimal {
    let formatter = NumberFormatter()
    formatter.generatesDecimalNumbers = true
    let value = formatter.number(from: string) as? NSDecimalNumber ?? 0
    return value.rounding(accordingToBehavior: RoundingBehavior(scale: 1)) as Decimal
}

哪里

class RoundingBehavior: NSDecimalNumberBehaviors {
    private let _scale: Int16

    init(scale: Int16) {
        _scale = scale
    }

    func roundingMode() -> NSDecimalNumber.RoundingMode {
        .plain
    }

    func scale() -> Int16 {
        _scale
    }

    func exceptionDuringOperation(_ operation: Selector, error: NSDecimalNumber.CalculationError, leftOperand: NSDecimalNumber, rightOperand: NSDecimalNumber?) -> NSDecimalNumber? {
        .notANumber
    }
}