今天,产品同学兴致冲冲的给我提了个小小的需求,面带微笑的说:小哥哥小哥哥,由于韩元的汇率很低,能不能把韩元的估值小数位精确到两位有效的精度?
具体我来解释一下,例如:0.0002345要处理成0.00023,0.0112345处理成0.011,就是说小数点后最多只能看到两个大于0的数字。
了解到这个问题之后我嘴角微微一笑,小case,不就是字符串的截取么。事实也是如此,字符串动态截取完全能实现这个功能,但是,对于如此懒得我,用腻了字符串截取,抓耳挠腮脑袋里过了很多种想法:正则、NSNumberFormatter、是否有系统函数等等,最终都不行,正则也不支持截取,只能匹配字符串。NSNumberFormatter的功能虽然非常强大,也只能设计精度样式,最小精度、最大精度等等,当然我在翻看系统函数时突然查到strchr(<#const char *__s#>, <#int __c#>),由于之前项目中使用到RAC,里面有个RAC_宏定义,这个强大的宏定义底层有一个#define keypath1(PATH) (((void)(NO && ((void)PATH, NO)), strchr(# PATH, '.') + 1)) ,其中就用到strchr()函数。
#define RAC_(TARGET, KEYPATH, NILVALUE) \
[[RACSubscriptingAssignmentTrampoline alloc] initWithTarget:(TARGET) nilValue:(NILVALUE)][@keypath(TARGET, KEYPATH)]
#define keypath(...) \
metamacro_if_eq(1, metamacro_argcount(__VA_ARGS__))(keypath1(__VA_ARGS__))(keypath2(__VA_ARGS__))
#define keypath1(PATH) \
(((void)(NO && ((void)PATH, NO)), strchr(# PATH, '.') + 1))
#define keypath2(OBJ, PATH) \
(((void)(NO && ((void)OBJ.PATH, NO)), # PATH))
strchr(<#const char *__s#>, <#int __c#>)函数具体的含义是:检索字符s从左到右第一次出现c之后的字符串(包含c),故而,突发奇想写出了如下实现:
/**
如果大于1则精确两位小数 如果小于1用于检索到两位有效数字
*/
-(NSString*)calculateTwoDigits
{
if ([self isEqualToString:@"0"] || self.doubleValue == 0) {
return @"0";
}
if (self.doubleValue >= 1) {
return [self calculateByRounding:2 mode:NSRoundDown];
}
unsigned long length = strspn(strchr(self.UTF8String, '.')+1, "0");
return [NSDecimalNumber decimalNumberWithString:[self substringToIndex:MIN(strlen(self.UTF8String), length + 4)]].stringValue;
}
unsigned long length = strspn(strchr(self.UTF8String, '.')+1, "0");
上面这句代码使用了strspn和strchr两个函数,strchr(self.UTF8String, '.')+1这段代码是过滤出字符串self中'.'之后的串(+1之后不包含'.'),如:0.123456,过滤之后就是123456。
然后使用strspn(<#const char *__s#>, <#const char *__charset#>)函数,该函数的意思是字符串s,从左到右连续出现字符charset的次数,返回值是unsinged long型,如:strspn("000011112345" , '0')输出结果是4.
两个函数合起来的功能就是输出小数点后连续出现'0'的次数。
最后,[NSDecimalNumber decimalNumberWithString:[self substringToIndex:MIN(strlen(self.UTF8String), length + 4)]].stringValue是进行截取0后面两位数字,在经过NSDecimalNumber初始化之后实现不补零。
总结:这个功能实现,实现起来其实很简单,虽然并不比直接截取字符串简单多少,但是执行速度还是比较快的。所以,对于我们程序员来说,不要急着实现某个功能,而应该多思考这种功能都可以用什么方式来实现,哪种方式最简单,从而精益求精。