2011-04-01 30 views
5

使用NSDecimalNumber我有一个计算得知是这样的:在Objective-C

Price = value * randomNumberBetween(decimalValueA, decimalValueB) 

我用花车/双打最初产生这个。然而,在查看一些更多的objective-c之后,曾多次提到计算货币时应该使用NSDecimalNumber。 我的问题是,我用这个“价格”的变量,在比较和东西,例如:

if (deposit/price) < 0.2 
    return price*0.05; 

使用NSDecimalNumber使得这一切变得更加困难。据我所知,我应该将任何幻数(在本例中为0.2和0.05)转换为NSDecimalNumber,然后我可以比较它们并使用诸如NSDecimalMultiply之类的函数。

另外,如果我有一个功能是一样的东西:

return (minRandomPercentage + ((maxRandomPercentage - minRandomPercentage) * (randomNumber) 

它最终成为嵌套函数的这个荒谬的字符串调用,如:

return [minRandomPercentage decimalNumberByAdding:[[maxRandomPercentage decimalNumberBySubtracting: minRandomPercentage] decimalNumberByMultiplyingBy:random]] 

这是严重怎么的Objective-C处理小数?任何人都可以给我任何线索,告诉我如何使这个难度更小?如果我可以和结果进行比较,而不必投射每一个魔法数字,我就可以与嵌套的函数调用一起生活。

+0

如果你在处理货币,为什么你不用原始整型数据类型?如果您的价值以“美分”而非“美元”(代替您自己的国际化)来表示,则您无需担心分数金额。 – 2011-04-01 03:27:25

回答

9

如果您无法负担处理rounding errors可能出现的标准基2浮点类型,则必须使用NSDecimal或NSDecimalNumber。 NSDecimal是一个C结构,Foundation提供了一个C接口来处理它。它提供的功能NSDecimalAdd,NSDecimalMultiply等

从​​:你可能会考虑C接口,如果你不需要把十进制数为对象,也就是说,如果你并不需要将它们存储在一个面向对象的集合,如NSArray或NSDictionary的实例。如果您需要最高效率,您也可以考虑使用C接口。 C接口比NSDecimalNumber类使用更少的内存。

如果您正在编写面向对象的代码,并且您没有与海量数据集进行交互,那么最好坚持使用NSDecimalNumber。如果你分析你的代码并发现使用NSDecimalNumber导致高内存开销,那么你可能需要考虑替代方案。

如果四舍五入错误不是问题,您也可以使用本机C标量。请参阅:How to add two NSNumber objects?

当您需要将数字传递给方法或将数字存储在集合中时,NSNumber和NSDecimalNumber将用作对象包装器。由于NSArray,NSSet,NSDictionary等仅允许您存储'id'类型的对象,因此您不能在本地存储整数,浮点数等。

如果您正在处理大型数据集并且可以承受舍入错误,则可以使用整数,浮点数,双精度等原始数据。然后,当你有你的结果,你需要存储它或将它传递给另一个对象时,可以相应地将它包含在一个NSNumber中。

如果您确实需要存储大量数字集合,那么使用C数组要比初始化和存储大量的NSNumber对象要高效得多。

+0

但是,如果我使用标量c类型,那么我没有得到小数的准确性吗?我相信在C中有一个十进制类型,但在头文件目录库中不存在... – link664 2011-04-01 03:02:18

+0

@ link664 - 我澄清了我的答案。 – 2011-04-01 03:26:00

1

说真的,这是你如何做iOS 10中的算术。正如您可能知道的那样,许多以10为底的精确表示的数字在基数2中没有确切的表示,并且在使用基础10系统(如货币或度量标准)时可能导致无法接受的舍入。

与内置数值类型(如int,float和double)不同,由NSDecimalNumber表示的值是对象。首先使用方法进行算术运算似乎很奇怪,但当您开始将这些值作为对象进行思考时,这会更有意义。

+0

那么,为了使用它们,我必须转换所有幻数吗?例如,我希望能够说[NSDecimalNumber numberWithFloat:0.25],但它给了我一个警告:“由于numberWithFloat是一个NSNumber函数,因此不匹配的指针类型将'NSNumber *'发送给参数类型'NSDecimalNumber *' – link664 2011-04-01 03:20:06

+1

@ link664: http://stackoverflow.com/questions/453691/how-use-nsdecimalnumber/454562#454562 – 2011-04-01 03:35:44