在 Objective-C 中使用 NSDecimalNumber

发布于 2024-10-29 02:23:02 字数 897 浏览 1 评论 0原文

我有一个类似这样的计算:

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 处理小数的方式真的是这样吗?谁能给我任何线索,告诉我如何让这件事变得不那么困难?如果我可以与结果进行比较,而不必强制转换我拥有的每个幻数,那么我可以接受嵌套函数调用。

I have a calculation that goes something like this:

Price = value * randomNumberBetween(decimalValueA, decimalValueB)

I was originally generating this using floats/doubles. However, after looking up a bit more on objective-c, it was mentioned numerous times that when calculating currency you should use NSDecimalNumber.
The issue I have is that I use this 'price' variable in comparisons and things, for example:

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

Using NSDecimalNumber makes this a lot more difficult. As far as I'm aware I should be converting any magic numbers (in this case 0.2 and 0.05) to NSDecimalNumber so then I can compare them and use functions such as NSDecimalMultiply.

Also, if I have a function that is something like:

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

it ends up becoming this ridiculous string of nested function calls like:

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

Is this seriously how objective-c deals with decimals? Can anyone give me any clues on how to make this a lot less arduous? I can live with the nested function calls if I could do comparisons with the result and not have to be casting every magic number I have.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

紫瑟鸿黎 2024-11-05 02:23:02

如果您无力处理舍入错误可能发生在标准基数 2 浮点类型中,您必须使用 NSDecimal 或 NSDecimalNumber。 NSDecimal 是一个 C 结构体,Foundation 提供了一个 C 接口来处理它。它提供函数 NSDecimalAdd、NSDecimalMultiply 等。

来自 数字和值编程指南:如果您不需要将十进制数字视为对象,也就是说,如果您不这样做,则可以考虑使用 C 接口不需要将它们存储在面向对象的集合中,例如 NSArray 或 NSDictionary 的实例。如果您需要最高效率,您也可以考虑 C 接口。 C 接口比 NSDecimalNumber 类更快并且使用更少的内存。

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

如果舍入误差不是问题,您还可以使用本机 C 标量。请参阅:如何添加两个 NSNumber 对象?

NSNumber 和 NSDecimalNumber当您需要将数字传递给方法或将数字存储在集合中时,它们用作对象包装器。由于 NSArray、NSSet、NSDictionary 等只允许存储 'id' 类型的对象,因此无法原生存储 int、float 等。

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

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

If you can't afford to deal with the rounding errors that can occur with the standard base-2 floating point types, you'll have to use NSDecimal or NSDecimalNumber. NSDecimal is a C struct, and Foundation provides a C interface for dealing with it. It provides functions NSDecimalAdd, NSDecimalMultiply, etc.

From the Number and Value Programming Guide: You might consider the C interface if you don’t need to treat decimal numbers as objects—that is, if you don’t need to store them in an object-oriented collection like an instance of NSArray or NSDictionary. You might also consider the C interface if you need maximum efficiency. The C interface is faster and uses less memory than the NSDecimalNumber class.

If you're writing object-oriented code, and you're not interacting with massive data sets, it might be best to stick with NSDecimalNumber. If you profile your code and find that using NSDecimalNumber is causing a high memory overhead, then you may need to consider alternatives.

If rounding errors are not a concern, you can also use native C scalars. See: How to add two NSNumber objects?

NSNumber and NSDecimalNumber are used as object wrappers when you need to pass a number to a method or store numbers in a collection. Since NSArray, NSSet, NSDictionary, etc. only allow you to store objects of type 'id', you can't store ints, floats, etc. natively.

If you're dealing with large data sets and can afford rounding errors, you can use ints, floats, doubles, etc. raw. Then when you have your result and you need to store it or pass it to another object, you can wrap it up in an NSNumber accordingly.

If you do have a need to store large collections of numbers, it's much more efficient to use C arrays than to initialize and store lots of NSNumber objects.

勿忘心安 2024-11-05 02:23:02

说真的,这就是在 iOS 中进行以 10 为底的算术运算的方法。您可能知道,许多以 10 为基数的数字没有以 2 为基数的精确表示,这可能会导致在使用以 10 为基数的系统(例如货币或公制测量)时出现不可接受的舍入情况。

NSDecimalNumber 表示的值是对象,与 int、float 和 double 等内置数字类型不同。乍一看,使用方法进行算术运算似乎很奇怪,但当您开始将值视为对象时,它就更有意义了。

Seriously, this is how you do base 10 arithmetic in iOS. As you're probably aware, many numbers that have exact representations in base 10 don't have exact representations in base 2, and that can lead to unacceptable rounding when working with base 10 systems like currency or metric measurements.

Values represented by NSDecimalNumber are objects, unlike built-in numeric types like int, float, and double. It seems odd at first to use methods for arithmetic operations, but it makes more sense when you start thinking about the values as objects.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文