float 浮点型计算会出现精度丢失问题
写了一个基本OC的计算类解决问题
临时用,很多地方可以修改或者改进
NSDecimalNumber
继承自NSNumber,苹果针对浮点类型计算精度问题提供出来的计算类,基于十进制的科学计数法来计算,同时可以指定舍入模式,一般用于货币计算。
.h文件
//
// CPCalculate.h
// CooperTest
//
// Created by jhf on 2019/2/12.
// Copyright © 2019年 jhf. All rights reserved.
//
#import <Foundation/Foundation.h>
@class CPCalculate;
typedef CPCalculate *(^CPCalculateBlock)(id num);
NS_ASSUME_NONNULL_BEGIN
@interface CPCalculate : NSObject
+ (CPCalculate *)initWithOriginNum:(id)num;
@property (nonatomic, strong) NSDecimalNumber *originNum;
@property (nonatomic, copy) CPCalculateBlock add;
@property (nonatomic, copy) CPCalculateBlock subtract;
@property (nonatomic, copy) CPCalculateBlock multiply;
@property (nonatomic, copy) CPCalculateBlock divide;
@end
NS_ASSUME_NONNULL_END
.m文件
//
// CPCalculate.m
// CooperTest
//
// Created by jhf on 2019/2/12.
// Copyright © 2019年 jhf. All rights reserved.
//
#import "CPCalculate.h"
@implementation CPCalculate
+ (CPCalculate *)initWithOriginNum:(id)num; {
NSDecimalNumber *number = [[self class] checkNumber:num];
if (!number) {
number = [[NSDecimalNumber alloc] initWithString:@"0"];
}
return [[[self class] alloc] initWithOriginNum:number];
}
- (instancetype)initWithOriginNum:(NSDecimalNumber *)num;
{
self = [super init];
if (self) {
_originNum = num;
[self setupBlock];
}
return self;
}
/**
设置block 调用
*/
- (void)setupBlock {
MJWeakSelf;
self.add = ^CPCalculate *(id num) {
[weakSelf add:num];
return weakSelf;
};
self.subtract = ^CPCalculate *(id num) {
[weakSelf subtract:num];
return weakSelf;
};
self.multiply = ^CPCalculate *(id num) {
[weakSelf multiply:num];
return weakSelf;
};
self.divide = ^CPCalculate *(id num) {
[weakSelf divide:num];
return weakSelf;
};
}
/**
加
@param num 加数
@return self
*/
- (CPCalculate *)add:(id)num; {
NSDecimalNumber *number = [[self class] checkNumber:num];
if (number) {
self.originNum = [self.originNum decimalNumberByAdding:number];
}
return self;
}
/**
减
@param num 减数
@return self
*/
- (CPCalculate *)subtract:(id)num; {
NSDecimalNumber *number = [[self class] checkNumber:num];
if (number) {
self.originNum = [self.originNum decimalNumberBySubtracting:number];
}
return self;
}
/**
乘
@param num 乘数
@return self
*/
- (CPCalculate *)multiply:(id)num; {
NSDecimalNumber *number = [[self class] checkNumber:num];
if (number) {
self.originNum = [self.originNum decimalNumberByMultiplyingBy:number];
}
return self;
}
/**
除
@param num 除数
@return self
*/
- (CPCalculate *)divide:(id)num; {
NSDecimalNumber *number = [[self class] checkNumber:num];
if (number) {
if ([[self class] aDecimalNumberWithStringOrNumberOrDecimalNumber:num compareAnotherDecimalNumberWithStringOrNumberOrDecimalNumber:@(0)] == 0) {
NSLog(@"除数不可为零");
} else {
self.originNum = [self.originNum decimalNumberByDividingBy:number];
}
}
return self;
}
/**
检查数字是否符合条件
@param number 数
@return NSDecimalNumber
*/
+ (NSDecimalNumber *)checkNumber:(id)number {
if ([number isKindOfClass:[NSString class]]) {
return [NSDecimalNumber decimalNumberWithString:number];
} else if([number isKindOfClass:[NSDecimalNumber class]]) {
return number;
} else if ([number isKindOfClass:[NSNumber class]]) {
return [NSDecimalNumber decimalNumberWithDecimal:[number decimalValue]];
} else{
NSLog(@"输入正确的类型");
return nil;
}
}
/**
两个数的比较
@param num1 第一个数
@param num2 第二个数
@return 比较结果
*/
+ (NSComparisonResult)aDecimalNumberWithStringOrNumberOrDecimalNumber:(id)num1 compareAnotherDecimalNumberWithStringOrNumberOrDecimalNumber:(id)num2 {
NSDecimalNumber *number1 = [CPCalculate checkNumber:num1];
NSDecimalNumber *number2 = [CPCalculate checkNumber:num2];
if (!(number1 && number2)) {
return false;
}
return [number1 compare:number2];
}
@end
测试使用
NSString *num1 = @"1.99999999999";
NSString *num2 = @"0.00000000001";
NSString *num3 = @"0.00000000002";
NSString *num4 = @"0.00000000003";
NSString *num5 = @"0.00000000004";
CPCalculate *cp = [CPCalculate initWithOriginNum:num1];
NSLog(@"%g", cp.add(num2).subtract(num3).multiply(num4).divide(num5).originNum.doubleValue);
结果 1.5