1.現(xiàn)象:
因APP業(yè)務(wù)需要,從后臺(tái)端取得軌跡點(diǎn)的string,包含一千及以上個(gè)經(jīng)緯度坐標(biāo)點(diǎn),數(shù)值精度為小數(shù)點(diǎn)后六位,string轉(zhuǎn)number類(lèi)型時(shí),精度仍然正確,又number轉(zhuǎn)double時(shí),精度出現(xiàn)變化,小數(shù)點(diǎn)第六位出現(xiàn)失真,例1.123456->1.123455999999或者1.123456000001這樣子。
2.解決辦法:
一開(kāi)始其實(shí)是用的float類(lèi)型,因?yàn)?位小數(shù)float類(lèi)型也足夠了,轉(zhuǎn)成double仍然沒(méi)解決問(wèn)題。查了下,由于double也就是浮點(diǎn)型類(lèi)型在計(jì)算機(jī)中的存在方式導(dǎo)致的此現(xiàn)象,無(wú)解。提工單給高德地圖,也無(wú)解,距離計(jì)算只接受double類(lèi)型,也沒(méi)有很好的辦法保證精度。
3.doble類(lèi)型不穩(wěn)定的解決辦法,(用于計(jì)算
1.與后臺(tái)等其他端的數(shù)據(jù)交互就用string格式;
2.本地?cái)?shù)據(jù)計(jì)算,非常精確的使用十進(jìn)制numberNSDecimalNumber格式來(lái)計(jì)算。
以下內(nèi)容來(lái)自引用原文鏈接
NSDecimalNumber類(lèi)型的的計(jì)算
NSDecimalNumber-十進(jìn)制數(shù),可以有小數(shù)點(diǎn),可以是正負(fù)數(shù)。繼承于NSNumber,常用于精確的數(shù)值計(jì)算,比如金融等方面。
-
+ (NSDecimalNumber *)decimalNumberWithMantissa:(unsigned long long)mantissa exponent:(short)exponent isNegative:(BOOL)flag;
mantissa:長(zhǎng)整形;exponent:指數(shù);flag:正負(fù)數(shù)。
-NSDecimalNumber *subtotalAmount = [NSDecimalNumber decimalNumberWithMantissa:1275 exponent:-2 isNegative:NO]; //12.75
subtotalAmount = [NSDecimalNumber decimalNumberWithMantissa:1275 exponent:2 isNegative:YES]; //-127500
-
+ (NSDecimalNumber *)decimalNumberWithDecimal:(NSDecimal)dcm;
將C語(yǔ)言NSDecimal類(lèi)型轉(zhuǎn)成一個(gè)十進(jìn)制數(shù)。
NSDecimalNumber *subtotalAmount = [NSDecimalNumber decimalNumberWithMantissa:1275 exponent:-2 isNegative:NO]; //12.75
NSDecimal decimalValue = [subtotalAmount decimalValue];
/**
* 數(shù)據(jù)結(jié)構(gòu):
(NSDecimal) decimalValue = {
_exponent = -2
_length = 1
_isNegative = 0
_isCompact = 1
_reserved = 0
_mantissa = ([0] = 1275, [1] = 0, [2] = 0, [3] = 0, [4] = 0, [5] = 0, [6] = 0, [7] = 0)
*/
subtotalAmount = [NSDecimalNumber decimalNumberWithDecimal:decimalValue]; //12.75
-
+ (NSDecimalNumber *)decimalNumberWithString:(nullable NSString *)numberValue;
將字符串轉(zhuǎn)成一個(gè)十進(jìn)制數(shù)。
NSDecimalNumber *discountAmount = [NSDecimalNumber decimalNumberWithString:@"-12.74"]; //-12.74
discountAmount = [NSDecimalNumber decimalNumberWithString:@"127.4"]; //127.4
-
+ (NSDecimalNumber *)decimalNumberWithString:(nullable NSString *)numberValue locale:(nullable id)locale;
這個(gè)有點(diǎn)復(fù)雜,locale代表一種格式,就像date的格式化一樣。這里的locale可以傳遞兩種格式
NSDictionary類(lèi)型:
NSDictionary *locale = [NSDictionary dictionaryWithObject:@"," forKey:NSLocaleDecimalSeparator]; //以","當(dāng)做小數(shù)點(diǎn)格式
NSDecimalNumber *discountAmount = [NSDecimalNumber decimalNumberWithString:@"123,40" locale:locale]; //123.4
NSLocale *locale = [[NSLocale alloc] initWithLocaleIdentifier:@"fr_FR"]; //法國(guó)數(shù)據(jù)格式,法國(guó)的小數(shù)點(diǎn)是','逗號(hào)
NSDecimalNumber *discountAmount = [NSDecimalNumber decimalNumberWithString:@"123,40" locale:locale]; //123.4
+(NSDecimalNumber *)zero; //0
+(NSDecimalNumber *)one; //1
+(NSDecimalNumber *)minimumDecimalNumber;
//-3402823669209384634633746074317682114550000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+(NSDecimalNumber *)maximumDecimalNumber;
//3402823669209384634633746074317682114550000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+(NSDecimalNumber *)notANumber;
//非數(shù)字,常用于對(duì)比,比如:
[[NSDecimalNumber notANumber] isEqualToNumber:myNumber];
- 加法運(yùn)算
-(NSDecimalNumber *)decimalNumberByAdding:(NSDecimalNumber *)decimalNumber;
-(NSDecimalNumber *)decimalNumberByAdding:(NSDecimalNumber *)decimalNumber withBehavior:(nullable id <NSDecimalNumberBehaviors>)behavior;
- 減法運(yùn)算
-(NSDecimalNumber *)decimalNumberBySubtracting:(NSDecimalNumber *)decimalNumber;
-(NSDecimalNumber *)decimalNumberBySubtracting:(NSDecimalNumber *)decimalNumber withBehavior:(nullable id <NSDecimalNumberBehaviors>)behavior;
- 乘法運(yùn)算
-(NSDecimalNumber *)decimalNumberByMultiplyingBy:(NSDecimalNumber *)decimalNumber;
-(NSDecimalNumber *)decimalNumberByMultiplyingBy:(NSDecimalNumber *)decimalNumber withBehavior:(nullable id <NSDecimalNumberBehaviors>)behavior;
- 除法運(yùn)算
-(NSDecimalNumber *)decimalNumberByDividingBy:(NSDecimalNumber *)decimalNumber;
-(NSDecimalNumber *)decimalNumberByDividingBy:(NSDecimalNumber *)decimalNumber withBehavior:(nullable id <NSDecimalNumberBehaviors>)behavior;
- a的n次方
-(NSDecimalNumber *)decimalNumberByRaisingToPower:(NSUInteger)power;
-(NSDecimalNumber *)decimalNumberByRaisingToPower:(NSUInteger)power withBehavior:(nullable id <NSDecimalNumberBehaviors>)behavior;
- 指數(shù)運(yùn)算
-(NSDecimalNumber *)decimalNumberByMultiplyingByPowerOf10:(short)power;
-(NSDecimalNumber *)decimalNumberByMultiplyingByPowerOf10:(short)power
withBehavior:(nullable id <NSDecimalNumberBehaviors>)behavior;
- 四舍五入運(yùn)算
-(NSDecimalNumber *)decimalNumberByRoundingAccordingToBehavior:(nullable id <NSDecimalNumberBehaviors>)behavior;
- 比較運(yùn)算
-(NSComparisonResult)compare:(NSNumber *)decimalNumber;
示例
NSDecimalNumber *discount1 = [NSDecimalNumber decimalNumberWithString:@"1.2"];
NSDecimalNumber *discount2 = [NSDecimalNumber decimalNumberWithString:@"1.3"];
NSComparisonResult result = [discount1 compare:discount2];
if (result == NSOrderedAscending) {
NSLog(@"1.2 < 1.3");
} else if (result == NSOrderedSame) {
NSLog(@"1.2 == 1.3");
} else if (result == NSOrderedDescending) {
NSLog(@"1.2 > 1.3");
}
注意:像NSNumber一樣,所有的NSDecimalNumber對(duì)象都是不可變額,這意味著在它們創(chuàng)建之后不能改變它們的值
*還有這個(gè)博客可以參考下,比較全 *[關(guān)于OC中的小數(shù)精確計(jì)算---NSDecimalNumber]
4. 數(shù)據(jù)類(lèi)型的復(fù)習(xí)
既然都接觸到基本數(shù)據(jù)類(lèi)型了 ,順便回憶整理下基本數(shù)據(jù)類(lèi)型好了
OC的基本數(shù)據(jù)類(lèi)型包括:整型、字符型、浮點(diǎn)型、布爾型、枚舉型。
- 一、整型
整型包含以下幾種類(lèi)型
1.short(短整型):內(nèi)存中通常占2字節(jié),即16位,取值范圍-32768 - +32767。
2.int(整型):通常占4字節(jié),取值范圍-2147483648 - 2147483647
3.long(長(zhǎng)整型):通常占8字節(jié)
4.long long(長(zhǎng)整型):通常占8字節(jié)
關(guān)于內(nèi)存中占用的字節(jié)數(shù),OC中并沒(méi)有硬性的規(guī)定,只是需要字節(jié)數(shù)符合以下條件:
short <= int <= long<= long long
// 基本數(shù)據(jù)類(lèi)型
int a = 10;
//下面的數(shù)已經(jīng)超出了int的取值范圍,編譯器會(huì)提出警告
int b = 10000000000000;
NSLog(@"%d",b);
//而這個(gè)數(shù)在long long的取值范圍內(nèi),所以不會(huì)溢出
long long c =1000000000000;
NSLog(@"%lld",c);
//mac系統(tǒng)下輸出各種類(lèi)型占用的位數(shù)
//輸出:short:2 int:4 long:8 long long:8
NSLog(@"short:%lu int:%lu long:%lu long long:%lu",sizeof(short),sizeof(int),sizeof(long),sizeof(long long));
整型有3種進(jìn)制表示方式:十進(jìn)制,八進(jìn)制,十六進(jìn)制
//八進(jìn)制,以0開(kāi)頭
int i8 = 010;
//十進(jìn)制
int i10 = 10;
//十六進(jìn)制,以0x或者0X開(kāi)頭
int i16 = 0x10;
//8 10 16
NSLog(@"%d %d %d",i8,i10,i16);
整型前加上unsigned關(guān)鍵字后,將它變成無(wú)符號(hào)整型,最高位不是符號(hào)位,而是數(shù)值位。無(wú)符號(hào)整數(shù)不能表示負(fù)數(shù),但是表示范圍大了。
short s = 32768;
unsigned short us = 32768;
//輸出-32768,32768,說(shuō)明正整數(shù)表示范圍比原先大了
NSLog(@"%d,%u",s,us);
- 二、字符型
字符型在OC中只占用一個(gè)字節(jié),OC字符變量不支持中文字符,字符需要使用’’包起來(lái),char類(lèi)型也可以看作整型值來(lái)使用,它是一個(gè)8位無(wú)符號(hào)整數(shù),取值范圍0-255。
另外可以通過(guò)轉(zhuǎn)義字符表示特殊字符常量:
| 轉(zhuǎn)義字符 | 說(shuō)明 |
| --------- | ----- | - 三、浮點(diǎn)型
浮點(diǎn)類(lèi)型包括float、double和long double,float占用4字節(jié),double占8字節(jié),long double占16字節(jié)。
OC中浮點(diǎn)數(shù)表示方法有兩種,一種是包含小數(shù)點(diǎn)的簡(jiǎn)單的浮點(diǎn)數(shù),另一種是科學(xué)計(jì)數(shù)法形式的浮點(diǎn)數(shù)
//利用浮點(diǎn)數(shù)計(jì)算類(lèi)型取值范圍
int i0 =-1/0.0;
int i1 = 1/0.0;
//輸出:int型取值范圍:-2147483648-2147483647
NSLog(@"int型取值范圍:%d-%d",i0,i1);
- 四、布爾型
OC中BOOL類(lèi)型有兩個(gè)值:YES和NO
BOOL b1 = YES;
if (b1) {
NSLog(@"%d",b1);
}
BOOL b1 = 10;
//輸出: YES: 10
if (b1) {
NSLog(@"YES: %d",b1);
}else{
NSLog(@"NO: %d",b1);
}
BOOL b1 = 768;
//輸出: NO: 0
if (b1) {
NSLog(@"YES: %d",b1);
}else{
NSLog(@"NO: %d",b1);
}
//注意:不要以為所有的非0整數(shù)變量賦給BOOL類(lèi)型就一定得到Y(jié)ES,上面的768的出的就是NO,BOOL類(lèi)型實(shí)質(zhì)上就是signed char。
- 五、枚舉型
一個(gè)變量只有幾種可能的值,這個(gè)變量就可以定義為枚舉變量
enum season {spring,summer,fall,winter};
enum season mySeason = spring;
mySeason = summer;
- 六、格式字符
在NSLog函數(shù)中我們使用了很多格式字符,如%d,%lu等。我們這里將介紹NSLog支持的格式字符。
原文鏈接 - 取值范圍
為了以后開(kāi)發(fā)中能夠方便查找,并正確的使用數(shù)據(jù)類(lèi)型,下面是部分?jǐn)?shù)據(jù)類(lèi)型的取值范圍:
int:-2147483648~2147483647
unsigned int:0~4294967295
short:-32768~32767
unsigned short:0~65535
long: -2147483648~2147483647
unsigned long:0~4294967295