NSDecimal 精确数值

NSDecimal

数据结构

  • 真是难以理解,水平不够,下面只好用 NSDecimalNumber 来初始化 NSDecimal 简单使用以下 NSDecimal 的相关内容;
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;

舍入

  • NSRoundingMode 舍入规则
typedef NS_ENUM(NSUInteger, NSRoundingMode) {
    NSRoundPlain,   // Round up on a tie
    NSRoundDown,    // Always down == truncate
    NSRoundUp,      // Always up
    NSRoundBankers  // on a tie round so last digit is even
};
  • 举例数据
// Original
//    value 1.2  1.21  1.25  1.35  1.27 原始值 
// Plain    1.2  1.2   1.3   1.4   1.3  四舍五入
// Down     1.2  1.2   1.2   1.3   1.2  向下取整
// Up       1.2  1.3   1.3   1.4   1.3  向上取整
// Bankers  1.2  1.2   1.2   1.4   1.3  四舍六入五留双(大学学的是不是还给老师了)
  • 举例代码

void NSDecimalRound(NSDecimal *result, const NSDecimal *number, NSInteger scale, NSRoundingMode roundingMode);

    NSDecimalNumber *decimalNumber1 = [NSDecimalNumber decimalNumberWithString:@"1.25"];
    NSDecimal decimal1 = [decimalNumber1 decimalValue];
    
    NSDecimal resDecimal;
    NSDecimalRound(&resDecimal, &decimal1, 1, NSRoundBankers);// 结果,操作数,保留小数位数,舍入规则
    NSDecimalNumber *resDecimalNumber = [NSDecimalNumber decimalNumberWithDecimal:resDecimal];
    
    NSLog(@"%@", resDecimalNumber);

操作

  • 是否是个数
    BOOL isNotANumber = NSDecimalIsNotANumber(&decimal);
  • 复制
    NSDecimal copyDecimal;
    NSDecimalCopy(&copyDecimal, &decimal);
  • 压缩:按文档说法,计算前先压缩,可以提高效率;
    NSDecimalCompact(&decimal);
  • 描述
    NSString *decimalString = NSDecimalString(&decimal, nil);
    NSLog(@"%@", decimalString);

计算

  • NSCalculationError 计算结果
    NSCalculationNoError = 0,
    NSCalculationLossOfPrecision, // Result lost precision
    NSCalculationUnderflow,       // Result became 0
    NSCalculationOverflow,        // Result exceeds possible representation
    NSCalculationDivideByZero
  • 准备 2 个 Decimal,下面都用这 2 个(只好 DecimalNumber 来初始化了)
    NSDecimalNumber *decimalNumber2_3 = [NSDecimalNumber decimalNumberWithString:@"2.3"];
    NSDecimal decimal2_3 = [decimalNumber2_3 decimalValue];
    NSDecimalNumber *decimalNumber3_4 = [NSDecimalNumber decimalNumberWithString:@"3.4"];
    NSDecimal decimal3_4 = [decimalNumber3_4 decimalValue];

    NSDecimal resultDecimal;
  • 规则化,相同的数值有很多表示方法,此函数即为了统一格式;
    NSCalculationError normalizeError = NSDecimalNormalize(&decimal2_3, &decimal3_4, NSRoundBankers);
    if (normalizeError == NSCalculationNoError) {
        NSLog(@"NSCalculationNoError");
    }
  • decimalA + decimalB
    NSCalculationError addError = NSDecimalAdd(&resultDecimal, &decimal2_3, &decimal3_4, NSRoundBankers);
    if (addError == NSCalculationNoError) {
        NSLog(@"add:%@", NSDecimalString(&resultDecimal,nil));
    }
  • decimalA - decimalB
    NSCalculationError subtractError = NSDecimalSubtract(&resultDecimal, &decimal2_3, &decimal3_4, NSRoundBankers);
    if (subtractError == NSCalculationNoError) {
        NSLog(@"subtract:%@", NSDecimalString(&resultDecimal,nil));
    }
  • decimalA * decimalB
    NSCalculationError multiplyError = NSDecimalMultiply(&resultDecimal, &decimal2_3, &decimal3_4, NSRoundBankers);
    if (multiplyError == NSCalculationNoError) {
        NSLog(@"multiply:%@", NSDecimalString(&resultDecimal,nil));
    }
  • decimalA / decimalB
    NSCalculationError divideError = NSDecimalDivide(&resultDecimal, &decimal2_3, &decimal3_4, NSRoundBankers);
    if (divideError == NSCalculationNoError) {
        NSLog(@"divide:%@", NSDecimalString(&resultDecimal,nil));
    }
  • decimalA ^ uintB
    NSCalculationError powerError = NSDecimalPower(&resultDecimal, &decimal2_3, 2, NSRoundBankers);
    if (powerError == NSCalculationNoError) {
        NSLog(@"power:%@", NSDecimalString(&resultDecimal,nil));
    }
  • decimalA * 10 ^ shortB
    NSCalculationError power10Error = NSDecimalMultiplyByPowerOf10(&resultDecimal, &decimal2_3, 2, NSRoundBankers);
    if (power10Error == NSCalculationNoError) {
        NSLog(@"power10:%@", NSDecimalString(&resultDecimal,nil));
    }