NSDecimalNumber 真的有必要完成一些非常简单的任务吗?

发布于 2024-09-12 09:56:21 字数 290 浏览 5 评论 0原文

开始很正常。我正在为 iPhone 编写复杂的计算应用程序。我决定使用 float 原语来表示数字。因此,是时候开始舍入和格式化输出了,但首先是舍入。我想将数字四舍五入到不同的小数位数。发现没有有用的C函数。好的,所以我可以自己写。但随后我有应用程序设置中的数字需要保留。 我发现只有对象才能被持久化。 所以我开始深入研究 NSNumber 和 NSDecimalNumber。尤其是后者,光是看着就让人不寒而栗。委托需要实现舍入,没有简单的算术运算符,而是特殊方法......:( 那么纯 C 的简单性还剩下什么呢?

还有其他方法可以简化这个吗?

It started quite normally. I'm writing complex calculation application for iPhone. I decided to use float primitive for representing numbers. So, time came to start rounding and formatting output, but first of all rounding. I want to round numbers to different number of decimal places. FOund out there is no useful C function. OK, so I can write my own. But then I have numbers from application settings to persist.
I found out only objects can be persisted.
So I started to dig in NSNumber and NSDecimalNumber. Especially the latter gives me shivers only when look at it. Delegate needed to implement roundings, no smiple arithmetic operators, special methods instead....:(
What is left then of pure C simplicity?

Is there any other way to simplify this?

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

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

发布评论

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

评论(2

メ斷腸人バ 2024-09-19 09:56:21

您可能可以使用 theValue - fmod(theValue, 0.01) 来四舍五入到最接近的 0.01。) 但请注意!

计算机实际上并不支持十进制数——即以十为基数的数字,我们在日常生活中使用它们的方式。它们使用二进制数,其中包括浮点数。它们也以二进制表示,这意味着“小数位数”并不总是浮点数的有意义的属性。

例如,浮点数不能精确表示 0.1,如果您尝试在代码中使用它,您将得到类似 0.1000000001 的结果。您获得的确切值因实现而异,并且无法通过减去差异来校正,因为计算机无法判断是否存在差异 - 差异尽可能接近 0.1。

这就是像 NSDecimalNumber 这样的类存在的原因。他们模拟十进制数学来给出对我们来说似乎更合理的值。它们很容易出现许多与浮点相同的问题,但具有不同的值(例如,1.0 / 3.0 不能完全用十进制表示,但它仍然是一个离散值。)

所以是的,如果你的数字 必须四舍五入到特定的小数位数,您需要使用 NSDecimalNumber 进行大多数小数运算。如果只是为了显示,您可以使用类似 NSNumberFormatter 的东西来获取显示值,而无需修改内存中的数字本身。

您问题的第二部分——在用户默认值中存储数值——很容易解决。 NSNumber “包装”一个原始数字类型,但它可以被解开:

NSNumber *n = [NSNumber numberWithDouble: 1.234567890];
double aDouble = [n doubleValue];

You could probably use theValue - fmod(theValue, 0.01) to round to, for this example, the nearest 0.01.) But be warned!

Computers don't actually work with decimal numbers--i.e. numbers in base ten, the way we use them in normal life. They work with binary numbers, and that includes floating-point numbers. They're represented in binary as well, and that means that "number of decimal places" is not always a meaningful property of a floating-point number.

For instance, a floating-point number cannot exactly represent 0.1, and you'll get something like 0.1000000001 if you try to use it in your code. The exact value you get varies by implementation, and is not correctable by subtracting the difference, as the computer can't tell that there is a difference--that's as close as it can get to 0.1.

This is why classes like NSDecimalNumber exist. They simulate decimal mathematics to give values that seem more sane to us. They're prone to many of the same problems as floating-point, but with different values (1.0 / 3.0 is not exactly representable in decimal, for instance, but it's still a discrete value.)

So yes, if your numbers must be rounded to a particular number of decimal places, you need to use NSDecimalNumber for most decimal operations. If it's just for display, you can use something like NSNumberFormatter instead to get the display value without modifying the number itself in memory.

The second part of your question--storing numeric values in user defaults, is easily solved. NSNumber "wraps" a primitive numeric type, but it can be unwrapped:

NSNumber *n = [NSNumber numberWithDouble: 1.234567890];
double aDouble = [n doubleValue];
罗罗贝儿 2024-09-19 09:56:21

每当您需要精确度时,尤其是对于任何会计/财务内容,请使用 NSDecimalNSDecimalNumber。对于任何其他需要准确性但不需要精确精度的情况,请使用double,而不是floatNSNumber 只是数字基元的 Obj-C 对象包装器。

有关格式化和舍入的信息,请参阅 NSNumberFormatter。任何 C 基元数字都可以包装成 NSNumber,然后您可以使用 NSNumberFormatter 将其转换为 NSString。乍一看可能有点笨拙,但在实际使用中,它效果很好,因为您可以获得非常高水平的格式控制。

Use NSDecimal and NSDecimalNumber whenever you need exact accuracy, especially for any accounting/financial stuff. For anything else that requires accuracy, but for which you don't need exact precision, use a double, not a float. NSNumber is simply an Obj-C object wrapper for number primitives.

For formatting and rounding, look at NSNumberFormatter. Any C primitive number can be wrapped up into an NSNumber, then you can use an NSNumberFormatter to convert it into an NSString. It might seem somewhat clumsy at first, but in real world use, it works pretty well, since you get a very high level of formatting control.

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