Is there a way to create an NSDecimal without using NSNumber and creating autoreleased objects?

痞子三分冷 提交于 2019-11-26 20:25:00

问题


I am carrying out a number of calculations using NSDecimal and am creating each NSDecimal struct using the following technique:

[[NSNumber numberWithFloat:kFloatConstant] decimalValue]

I am using NSDecimal to avoid using autoreleased NSDecimalNumber objects (if the NSDecimalNumber approach to accurate calculations is used). However it seems that the NSNumber creation mechanism also returns an autoreleased NSNumber from which the decimal value is extracted.

Is there a way to create an NSDecimal without using NSNumber and creating autoreleased objects?


回答1:


Unfortunately, Apple does not provide any easy ways of putting values into an NSDecimal struct. The struct definition itself can be found in the NSDecimal.h header:

typedef struct {
    signed   int _exponent:8;
    unsigned int _length:4;     // length == 0 && isNegative -> NaN
    unsigned int _isNegative:1;
    unsigned int _isCompact:1;
    unsigned int _reserved:18;
    unsigned short _mantissa[NSDecimalMaxSize];
} NSDecimal;

but I don't know that I would go around trying to reverse-engineer how the structs hold values. The underscores on the fields in the struct indicate that these are private and subject to change. I don't imagine that a lot of changes occur in the low-level NSDecimal functions, but I'd be nervous about things breaking at some point.

Given that, initializing an NSDecimal from a floating point number is best done in the way that you describe. However, be aware that any time you use a floating point value you are losing the precision you've gained by using an NSDecimal, and will be subjecting yourself to floating point errors.

I always work only with NSDecimals within my high-precision calculations, and take in and export NSStrings for exchanging these values with the outside world. To create an NSDecimal based on an NSString, you can use the approach we take in the Core Plot framework:

NSDecimal CPDecimalFromString(NSString *stringRepresentation)
{
    NSDecimal result;
    NSScanner *theScanner = [[NSScanner alloc] initWithString:stringRepresentation];
    [theScanner scanDecimal:&result];
    [theScanner release];

    return result;
}

Using an NSScanner instead of NSDecimalNumber -initWithString:locale: is about 90% faster in my benchmarks.




回答2:


To answer the “without autoreleased objects” part, simply:

NSDecimalNumber *intermediateNumber = [[NSDecimalNumber alloc] initWithFloat:kFloatConstant];
NSDecimal decimal = [intermediateNumber decimalValue];
[intermediateNumber release];


来源:https://stackoverflow.com/questions/2035421/is-there-a-way-to-create-an-nsdecimal-without-using-nsnumber-and-creating-autore

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!