Kyl*_*man 52 formatting data-conversion nsnumber human-readable ios
如何将超过3位的所有数字转换为4位或更少的数字?
这正是我的意思:
10345 = 10.3k
10012 = 10k
123546 = 123.5k
4384324 = 4.3m
Run Code Online (Sandbox Code Playgroud)
舍入并不完全重要,但还有一个额外的好处.
我已经研究过NSNumberFormatter但是没有找到合适的解决方案,而且我还没有在SO上找到合适的解决方案.非常感谢任何帮助,谢谢!
Luc*_*aco 58
-(NSString*) suffixNumber:(NSNumber*)number
{
if (!number)
return @"";
long long num = [number longLongValue];
int s = ( (num < 0) ? -1 : (num > 0) ? 1 : 0 );
NSString* sign = (s == -1 ? @"-" : @"" );
num = llabs(num);
if (num < 1000)
return [NSString stringWithFormat:@"%@%lld",sign,num];
int exp = (int) (log10l(num) / 3.f); //log10l(1000));
NSArray* units = @[@"K",@"M",@"G",@"T",@"P",@"E"];
return [NSString stringWithFormat:@"%@%.1f%@",sign, (num / pow(1000, exp)), [units objectAtIndex:(exp-1)]];
}
Run Code Online (Sandbox Code Playgroud)
样品用法
NSLog(@"%@",[self suffixNumber:@100]); // 100
NSLog(@"%@",[self suffixNumber:@1000]); // 1.0K
NSLog(@"%@",[self suffixNumber:@1500]); // 1.5K
NSLog(@"%@",[self suffixNumber:@24000]); // 24.0K
NSLog(@"%@",[self suffixNumber:@99900]); // 99.9K
NSLog(@"%@",[self suffixNumber:@99999]); // 100.0K
NSLog(@"%@",[self suffixNumber:@109999]); // 110.0K
NSLog(@"%@",[self suffixNumber:@5109999]); // 5.1M
NSLog(@"%@",[self suffixNumber:@8465445223]); // 8.5G
NSLog(@"%@",[self suffixNumber:[NSNumber numberWithInt:-120]]); // -120
NSLog(@"%@",[self suffixNumber:[NSNumber numberWithLong:-5000000]]); // -5.0M
NSLog(@"%@",[self suffixNumber:[NSNumber numberWithDouble:-3.5f]]); // -3
NSLog(@"%@",[self suffixNumber:[NSNumber numberWithDouble:-4000.63f]]); // -4.0K
Run Code Online (Sandbox Code Playgroud)
[ 更新 ]
Swift版本如下:
func suffixNumber(number:NSNumber) -> NSString {
var num:Double = number.doubleValue;
let sign = ((num < 0) ? "-" : "" );
num = fabs(num);
if (num < 1000.0){
return "\(sign)\(num)";
}
let exp:Int = Int(log10(num) / 3.0 ); //log10(1000));
let units:[String] = ["K","M","G","T","P","E"];
let roundedNum:Double = round(10 * num / pow(1000.0,Double(exp))) / 10;
return "\(sign)\(roundedNum)\(units[exp-1])";
}
Run Code Online (Sandbox Code Playgroud)
样品用法
print(self.suffixNumber(NSNumber(long: 100))); // 100.0
print(self.suffixNumber(NSNumber(long: 1000))); // 1.0K
print(self.suffixNumber(NSNumber(long: 1500))); // 1.5K
print(self.suffixNumber(NSNumber(long: 24000))); // 24.0K
print(self.suffixNumber(NSNumber(longLong: 99900))); // 99.9K
print(self.suffixNumber(NSNumber(longLong: 99999))); // 100.0K
print(self.suffixNumber(NSNumber(longLong: 109999))); // 110.0K
print(self.suffixNumber(NSNumber(longLong: 5109999))); // 5.1K
print(self.suffixNumber(NSNumber(longLong: 8465445223))); // 8.5G
print(self.suffixNumber(NSNumber(long: -120))); // -120.0
print(self.suffixNumber(NSNumber(longLong: -5000000))); // -5.0M
print(self.suffixNumber(NSNumber(float: -3.5))); // -3.5
print(self.suffixNumber(NSNumber(float: -4000.63))); // -4.0K
Run Code Online (Sandbox Code Playgroud)
希望能帮助到你
gbi*_*eau 36
在这里我的版本!感谢以前的答案.这个版本的目标是:
NSNumberFormatter
以避免位置问题(例如逗号而不是法语中的点)NSNumberFormatterRoundingMode
您可以使用所有精彩NSNumberFormatter
选项来满足您的需求,请参阅NSNumberFormatter类参考
代码(要点):
extension Int {
func formatUsingAbbrevation () -> String {
let numFormatter = NSNumberFormatter()
typealias Abbrevation = (threshold:Double, divisor:Double, suffix:String)
let abbreviations:[Abbrevation] = [(0, 1, ""),
(1000.0, 1000.0, "K"),
(100_000.0, 1_000_000.0, "M"),
(100_000_000.0, 1_000_000_000.0, "B")]
// you can add more !
let startValue = Double (abs(self))
let abbreviation:Abbrevation = {
var prevAbbreviation = abbreviations[0]
for tmpAbbreviation in abbreviations {
if (startValue < tmpAbbreviation.threshold) {
break
}
prevAbbreviation = tmpAbbreviation
}
return prevAbbreviation
} ()
let value = Double(self) / abbreviation.divisor
numFormatter.positiveSuffix = abbreviation.suffix
numFormatter.negativeSuffix = abbreviation.suffix
numFormatter.allowsFloats = true
numFormatter.minimumIntegerDigits = 1
numFormatter.minimumFractionDigits = 0
numFormatter.maximumFractionDigits = 1
return numFormatter.stringFromNumber(NSNumber (double:value))!
}
}
let testValue:[Int] = [598, -999, 1000, -1284, 9940, 9980, 39900, 99880, 399880, 999898, 999999, 1456384, 12383474]
testValue.forEach() {
print ("Value : \($0) -> \($0.formatUsingAbbrevation ())")
}
Run Code Online (Sandbox Code Playgroud)
结果:
Value : 598 -> 598
Value : -999 -> -999
Value : 1000 -> 1K
Value : -1284 -> -1.3K
Value : 9940 -> 9.9K
Value : 9980 -> 10K
Value : 39900 -> 39.9K
Value : 99880 -> 99.9K
Value : 399880 -> 0.4M
Value : 999898 -> 1M
Value : 999999 -> 1M
Value : 1456384 -> 1.5M
Value : 12383474 -> 12.4M
Run Code Online (Sandbox Code Playgroud)
小智 35
我遇到了同样的问题并且最终使用了Kyle的方法,但不幸的是,当使用120000这样的数字时它会中断,显示12k而不是120K,我需要显示小数字,如:1.1K,而不是向下舍入到1K.
所以这是我对凯尔最初想法的编辑:
Results:
[self abbreviateNumber:987] ---> 987
[self abbreviateNumber:1200] ---> 1.2K
[self abbreviateNumber:12000] ----> 12K
[self abbreviateNumber:120000] ----> 120K
[self abbreviateNumber:1200000] ---> 1.2M
[self abbreviateNumber:1340] ---> 1.3K
[self abbreviateNumber:132456] ----> 132.5K
-(NSString *)abbreviateNumber:(int)num {
NSString *abbrevNum;
float number = (float)num;
//Prevent numbers smaller than 1000 to return NULL
if (num >= 1000) {
NSArray *abbrev = @[@"K", @"M", @"B"];
for (int i = abbrev.count - 1; i >= 0; i--) {
// Convert array index to "1000", "1000000", etc
int size = pow(10,(i+1)*3);
if(size <= number) {
// Removed the round and dec to make sure small numbers are included like: 1.1K instead of 1K
number = number/size;
NSString *numberString = [self floatToString:number];
// Add the letter for the abbreviation
abbrevNum = [NSString stringWithFormat:@"%@%@", numberString, [abbrev objectAtIndex:i]];
}
}
} else {
// Numbers like: 999 returns 999 instead of NULL
abbrevNum = [NSString stringWithFormat:@"%d", (int)number];
}
return abbrevNum;
}
- (NSString *) floatToString:(float) val {
NSString *ret = [NSString stringWithFormat:@"%.1f", val];
unichar c = [ret characterAtIndex:[ret length] - 1];
while (c == 48) { // 0
ret = [ret substringToIndex:[ret length] - 1];
c = [ret characterAtIndex:[ret length] - 1];
//After finding the "." we know that everything left is the decimal number, so get a substring excluding the "."
if(c == 46) { // .
ret = [ret substringToIndex:[ret length] - 1];
}
}
return ret;
}
Run Code Online (Sandbox Code Playgroud)
我希望这可以帮助你们.
Abd*_*ؤمن 24
FlávioJVieira Caetano的答案转换为Swift 3.0
extension Int {
var abbreviated: String {
let abbrev = "KMBTPE"
return abbrev.characters.enumerated().reversed().reduce(nil as String?) { accum, tuple in
let factor = Double(self) / pow(10, Double(tuple.0 + 1) * 3)
let format = (factor.truncatingRemainder(dividingBy: 1) == 0 ? "%.0f%@" : "%.1f%@")
return accum ?? (factor > 1 ? String(format: format, factor, String(tuple.1)) : nil)
} ?? String(self)
}
}
Run Code Online (Sandbox Code Playgroud)
小智 13
我遇到了类似的问题,试图在Shinobi Charts中格式化y轴值.它需要使用NSNumberFormatter,所以我最终想出了这个
NSNumberFormatter *numFormatter = [[NSNumberFormatter alloc] init];
[numFormatter setPositiveFormat:@"0M"];
[numFormatter setMultiplier:[NSNumber numberWithDouble:0.000001]];
Run Code Online (Sandbox Code Playgroud)
获取格式化的值
NSString *formattedNumber = [numFormatter stringFromNumber:[NSNumber numberWithInteger:4000000]]; //@"4M"
Run Code Online (Sandbox Code Playgroud)
此解决方案没有包含舍入,但如果您(或其他任何人)只需要简单的东西,这可能会有效.如果需要千位而不是百万,则在setPostiveFormat方法中将"M"更改为"K",并将乘数中的NSNumber值更改为0.001.
Kyl*_*man 10
以下是我提出的两种方法,它们共同发挥作用以产生预期的效果.这也将自动向上舍入.这也将通过传递int dec来指定可见的总数.
此外,在浮到字符串的方法,您可以更改@"%.1f"
到@"%.2f"
,@"%.3f"
等来告诉它有多少可见小数,小数点后显示.
For Example:
52935 ---> 53K
52724 ---> 53.7K
-(NSString *)abbreviateNumber:(int)num withDecimal:(int)dec {
NSString *abbrevNum;
float number = (float)num;
NSArray *abbrev = @[@"K", @"M", @"B"];
for (int i = abbrev.count - 1; i >= 0; i--) {
// Convert array index to "1000", "1000000", etc
int size = pow(10,(i+1)*3);
if(size <= number) {
// Here, we multiply by decPlaces, round, and then divide by decPlaces.
// This gives us nice rounding to a particular decimal place.
number = round(number*dec/size)/dec;
NSString *numberString = [self floatToString:number];
// Add the letter for the abbreviation
abbrevNum = [NSString stringWithFormat:@"%@%@", numberString, [abbrev objectAtIndex:i]];
NSLog(@"%@", abbrevNum);
}
}
return abbrevNum;
}
- (NSString *) floatToString:(float) val {
NSString *ret = [NSString stringWithFormat:@"%.1f", val];
unichar c = [ret characterAtIndex:[ret length] - 1];
while (c == 48 || c == 46) { // 0 or .
ret = [ret substringToIndex:[ret length] - 1];
c = [ret characterAtIndex:[ret length] - 1];
}
return ret;
}
Run Code Online (Sandbox Code Playgroud)
希望这可以帮助其他需要它的人!
在尝试了几个这样的解决方案后,Luca laco看起来最接近,但我对他的方法做了一些修改,以便更多地控制将出现多少位数(即如果你想要120.3K更短,你可以限制为120K).另外,我添加了一个额外的步骤,确保像999,999这样的数字不会显示为1000.0K,而是1.0M.
/*
With "onlyShowDecimalPlaceForNumbersUnder" = 10:
Original number: 598 - Result: 598
Original number: 1000 - Result: 1.0K
Original number: 1284 - Result: 1.3K
Original number: 9980 - Result: 10K
Original number: 39900 - Result: 40K
Original number: 99880 - Result: 100K
Original number: 999898 - Result: 1.0M
Original number: 999999 - Result: 1.0M
Original number: 1456384 - Result: 1.5M
Original number: 12383474 - Result: 12M
*/
- (NSString *)suffixNumber:(NSNumber *)number
{
if (!number)
return @"";
long long num = [number longLongValue];
if (num < 1000)
return [NSString stringWithFormat:@"%lld",num];
int exp = (int) (log(num) / log(1000));
NSArray * units = @[@"K",@"M",@"G",@"T",@"P",@"E"];
int onlyShowDecimalPlaceForNumbersUnder = 10; // Either 10, 100, or 1000 (i.e. 10 means 12.2K would change to 12K, 100 means 120.3K would change to 120K, 1000 means 120.3K stays as is)
NSString *roundedNumStr = [NSString stringWithFormat:@"%.1f", (num / pow(1000, exp))];
int roundedNum = [roundedNumStr integerValue];
if (roundedNum >= onlyShowDecimalPlaceForNumbersUnder) {
roundedNumStr = [NSString stringWithFormat:@"%.0f", (num / pow(1000, exp))];
roundedNum = [roundedNumStr integerValue];
}
if (roundedNum >= 1000) { // This fixes a number like 999,999 from displaying as 1000K by changing it to 1.0M
exp++;
roundedNumStr = [NSString stringWithFormat:@"%.1f", (num / pow(1000, exp))];
}
NSString *result = [NSString stringWithFormat:@"%@%@", roundedNumStr, [units objectAtIndex:(exp-1)]];
NSLog(@"Original number: %@ - Result: %@", number, result);
return result;
}
Run Code Online (Sandbox Code Playgroud)
我知道已经有很多答案和不同的方法,但这就是我用更实用的方法解决它的方法:
extension Int {
var abbreviated: String {
let abbrev = "KMBTPE"
return abbrev.characters
.enumerated()
.reversed()
.reduce(nil as String?) { accum, tuple in
let factor = Double(self) / pow(10, Double(tuple.0 + 1) * 3)
let format = (factor - floor(factor) == 0 ? "%.0f%@" : "%.1f%@")
return accum ?? (factor >= 1 ? String(format: format, factor, String(tuple.1)) : nil)
} ?? String(self)
}
}
Run Code Online (Sandbox Code Playgroud)
Swift-4 Doble extension
- 这适用于所有情况。
extension Double {
// Formatting double value to k and M
// 1000 = 1k
// 1100 = 1.1k
// 15000 = 15k
// 115000 = 115k
// 1000000 = 1m
func formatPoints() -> String{
let thousandNum = self/1000
let millionNum = self/1000000
if self >= 1000 && self < 1000000{
if(floor(thousandNum) == thousandNum){
return ("\(Int(thousandNum))k").replacingOccurrences(of: ".0", with: "")
}
return("\(thousandNum.roundTo(places: 1))k").replacingOccurrences(of: ".0", with: "")
}
if self > 1000000{
if(floor(millionNum) == millionNum){
return("\(Int(thousandNum))k").replacingOccurrences(of: ".0", with: "")
}
return ("\(millionNum.roundTo(places: 1))M").replacingOccurrences(of: ".0", with: "")
}
else{
if(floor(self) == self){
return ("\(Int(self))")
}
return ("\(self)")
}
}
/// Returns rounded value for passed places
///
/// - parameter places: Pass number of digit for rounded value off after decimal
///
/// - returns: Returns rounded value with passed places
func roundTo(places:Int) -> Double {
let divisor = pow(10.0, Double(places))
return (self * divisor).rounded() / divisor
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
22379 次 |
最近记录: |