是否有方法覆盖Double,使其在swift中默认为每两个双精度值2个小数位?
我正在用swift 4编写一个应用程序,我不想每次创建double时都对double值进行四舍五入。默认情况下,我希望将其设置为小数点后2位 双重值将全部用于货币显示/保存目的 例如,10.00美元,而是像:10.0一样节省 我正在寻找可以覆盖双重功能的东西是否有方法覆盖Double,使其在swift中默认为每两个双精度值2个小数位?,swift,double,overriding,decimal,Swift,Double,Overriding,Decimal,我正在用swift 4编写一个应用程序,我不想每次创建double时都对double值进行四舍五入。默认情况下,我希望将其设置为小数点后2位 双重值将全部用于货币显示/保存目的 例如,10.00美元,而是像:10.0一样节省 我正在寻找可以覆盖双重功能的东西 提前感谢您的帮助我可以为您的问题提出两种解决方案。但我不确定他们是否能满足你的需要。首先是覆盖Double货币值变量的didSet,如下所示: var currencyValue: Double = 0.0 { didSet {
提前感谢您的帮助我可以为您的问题提出两种解决方案。但我不确定他们是否能满足你的需要。首先是覆盖
Double
货币值变量的didSet
,如下所示:
var currencyValue: Double = 0.0 {
didSet {
// Do the rounding
let divisor = pow(10.0, 2) // 2 is the place number
currencyValue = (currencyValue * divisor).rounded() / divisor
}
}
第二种方法是使用extensions
为Double
创建一个新的init
函数,该函数立即进行取整
extension Double {
init(value: Double, roundTo places: Double) {
let divisor = pow(10.0, places)
self = (value * divisor).rounded() / divisor
}
}
// Use the extension initialization
Double(value: 10.22, roundTo: 2)
虽然这些可以作为解决方案,但我必须同意。使用NumberFormatter
可以让您轻松地在本地格式化货币。希望这有帮助
编辑:
所以,为了实现你真正想要的,我们需要做一些小的调整。我将更新覆盖方法:
var currencyValue: String = "0.00" {
get {
// Convert String value to Double
let doubleValue = Double(currencyValue)
// Do the rounding
let divisor = pow(10.0, 2) // 2 is the place number
doubleValue = (doubleValue * divisor).rounded() / divisor
// Format the number
let numberFormatter = NumberFormatter()
numberFormatter.numberStyle = NumberFormatter.Style.decimal
numberFormatter.minimumFractionDigits = 2 // We want at least 2 decimal places
if let formattedString = numberFormatter.string(from: NSNumber(doubleValue)) {
return formattedString
}
return currencyValue
}
}
您可以这样使用它:
var double = 10.2
currencyValue = "\(double)" // Setting the double value as String
print(currencyValue) // will print 10.20
它是一个仅与货币相关的应用程序。因此,我不希望每次都处理舍入函数,而是希望能够在默认情况下处理它
对于货币应用程序,最好避免Float
&Double
。这些类型基于二进制浮点数,不精确到小数点
例如,取34美分/便士/任何货币,其中100美分等于1美元/英镑/任何货币,那么你可以用小数点0.34表示,或者用3/10+4/100表示1/(10^n)分数的总和。现在二进制浮点(和定点)使用1/(2^n)个分数的和。所以34/100=1/4(25/100)+9/100=1/4+1/16+275/10000=1/4+1/16+1/64+。。。(此总和可以是有限的,也可以是无限的,具体取决于小数点)
请注意,考虑到这个二进制基数,您要求有两个小数位是不可能的,因为无论您将自己限制为小数点的位数是多少,某些小数位都是不精确的
那么解决方案是什么呢?整数(或定点数字,见下文)
如果您只需要支持十进制货币,即小单位是大单位的1/100(如美元/美分、英镑/便士),那么您可以简单地使用足够大的整数,并将金额保持在小单位。例如,将12.34美元存储为1234美分。若你们需要更高的精度(比如说你们在计算股价等),你们可以将你们的值存储为小单位的一些(十进制)部分,比如1/100美分。这样,所有计算都使用精确的整数算术运算。对于字符串转换,您需要添加/删除货币点,然后进行整数转换,或者使用余数/除法将存储的值拆分为其组件并格式化每个组件
如果您需要支持非十进制货币,或者您需要的范围比存储为最大整数类型中允许的较小单位(部分)的范围更大,那么您可以将大单位和小单位存储为两个整数值,并自行处理它们之间的进位操作
您可以在Swift中将操作包装为值(struct
)类型
有些语言支持十进制定点算法,或者提供了类似于我们刚才描述的库;如果你看的话,那里可能有一个斯威夫特图书馆。(例如,请参见Python的链接,该链接还涵盖了上面解释的要点。)
如果您希望继续使用可用的类型,请查看使用Decimal
,这是一种十进制浮点类型,提供38位十进制精度。它不是专门为货币设计的,但您可以使用NSDecimalRound
将数字保留到所需的小数位数(甚至支持四舍五入);为了满足您自动执行此操作的特定要求,您必须包装/扩展并实现您自己的运算符,该运算符将标准运算符与四舍五入合并到所需的位数
希望这对你的帮助大于困惑 没有必要每两个回合都进行一次。只要在需要向用户显示double时使用适当的
NumberFormatter
。您是否使用这两个小数位来表示货币值?CRD,是的。它是一个仅与货币相关的应用程序。因此,我不希望每次都处理舍入函数,而是希望能够在默认情况下执行。@Smartcat,我以前看过这篇文章,不幸的是,这不是我想要的。为了更清楚,我编辑了我的问题。虽然你的答案与我想要的很接近,但它仍然不适用于10.00美元这样的值。无论如何,我想我会听取你和@rmaddy的建议,使用NumberFormatter。这是额外的工作,但很有效。谢谢你的建议。我要试试