iOS convertit les grands nombres en plus petit format

Comment puis-je convertir tous les nombres qui sont plus de 3 chiffres en bas à 4 chiffres ou moins?

C'est exactement ce que je veux dire:

10345 = 10.3k
10012 = 10k
123546 = 123.5k
4384324 = 4.3m

Arrondissement n'est pas entièrement important, mais un plus.

j'ai regardé dans NSNumberFormatter mais n'ont pas trouvé la bonne solution, et je dois encore trouver une bonne solution ici sur SO. Toute aide est grandement appréciée, merci!

46
demandé sur Rajesh 2013-08-16 10:37:08

20 réponses

-(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)]];
}

exemple d'utilisation

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

[ mise à Jour ]

version Swift ci-dessous:

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])";
}

exemple d'utilisation

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

j'Espère que ça aide

52
répondu Luca Iaco 2017-02-02 07:51:27

j'ai eu le même problème et j'ai fini par utiliser L'approche de Kyle, mais malheureusement il se brise quand des nombres comme 120000 sont utilisés, montrant 12k au lieu de 120K et j'ai dû montrer de petits nombres comme: 1.1 K au lieu d'arrondir à 1K.

alors voici mon montage de L'idée originale de Kyle:

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;
}

J'espère que ça vous aidera.

35
répondu Ricardo Corrêa de Souza 2014-04-17 06:22:02

voici ma version ! Merci aux réponses précédentes. Les buts de cette version est:

  • ont un meilleur contrôle de seuil parce que les détails de petit nombre sont plus importants que les détails de très grand nombre
  • utiliser autant que possible NSNumberFormatter pour éviter les problèmes d'emplacement (comma au lieu de point en français)
  • éviter".Les nombres de 0" et bien arrondis, qui peuvent être personnalisés en utilisant NSNumberFormatterRoundingMode

Vous pouvez utiliser tous les merveilleux NSNumberFormatter options pour répondre à vos besoins, consultez la section NSNumberFormatter Classe de Référence

le code ( gist ):

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 : \("151900920") -> \("151900920".formatUsingAbbrevation ())")
}

résultat:

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
31
répondu gbitaudeau 2017-03-03 09:46:17

Flávio J Vieira Caetano's answer converti en 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)
    }
}
20
répondu AbdulMomen عبدالمؤمن 2017-05-23 12:34:30

j'ai rencontré un problème similaire en essayant de formater les valeurs de L'axe des ordonnées Shinobi. Il a fallu utiliser un NSNumberFormatter, donc je suis finalement venu avec ce

NSNumberFormatter *numFormatter = [[NSNumberFormatter alloc] init];
[numFormatter setPositiveFormat:@"0M"];
[numFormatter setMultiplier:[NSNumber numberWithDouble:0.000001]];

pour obtenir une valeur formatée

NSString *formattedNumber = [numFormatter stringFromNumber:[NSNumber numberWithInteger:4000000]]; //@"4M"

cette solution n'a pas d'arrondissement inclus, mais si vous (ou quelqu'un d'autre) a juste besoin de quelque chose de simple, cela pourrait fonctionner. Si vous avez besoin par le millier au lieu de par le million, vous changez le "M" en un "K" dans le setPostiveFormat méthode, et changer la valeur du NN-Number dans le multiplicateur à 0.001 .

13
répondu Taidg Murphy 2013-08-22 19:31:38

Voici deux méthodes que j'ai qui travaillent ensemble pour produire l'effet désiré. Cela se terminera aussi automatiquement. Cela précisera également combien de nombres totaux seront visibles en passant le déc int.

aussi, dans la méthode float to string, vous pouvez changer le @"%.1f" en @"%.2f" , @"%.3f" , etc pour lui dire combien de décimales visibles montrer après le point décimal.

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;
}

Espérons que cette aide quelqu'un d'autre qui en a besoin!

10
répondu Kyle Begeman 2013-08-18 03:48:12

après avoir essayé quelques-unes de ces solutions, Luca laco semble l'avoir le plus proche, mais j'ai fait quelques modifications à sa méthode afin d'avoir plus de contrôle sur le nombre de chiffres apparaîtra (i.e. si vous voulez 120.3 K pour être plus court, vous pouvez le limiter à 120K). En outre, j'ai ajouté une étape supplémentaire qui assure un nombre comme 999 999 n'apparaît pas comme 1000.0 K, plutôt 1.0 M.

/*
 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;
}
7
répondu beebcon 2014-06-03 18:59:36

je sais qu'il y a déjà beaucoup de réponses et de façons différentes, mais c'est comme ça que je l'ai résolu avec une approche plus fonctionnelle:

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)
    }
}
5
répondu Flávio J Vieira Caetano 2017-02-13 17:02:04

version Swift

traduction directe de la version de L'objectif C

func abbreviateNumber(num: NSNumber) -> NSString {
    var ret: NSString = ""
    let abbrve: [String] = ["K", "M", "B"]

    var floatNum = num.floatValue

    if floatNum > 1000 {

        for i in 0..<abbrve.count {
            let size = pow(10.0, (Float(i) + 1.0) * 3.0)
            println("\(size)   \(floatNum)")
            if (size <= floatNum) {
                let num = floatNum / size
                let str = floatToString(num)
                ret = NSString(format: "%@%@", str, abbrve[i])
            }
        }
    } else {
        ret = NSString(format: "%d", Int(floatNum))
    }

    return ret
}

func floatToString(val: Float) -> NSString {
    var ret = NSString(format: "%.1f", val)
    var c = ret.characterAtIndex(ret.length - 1)

    while c == 48 {
        ret = ret.substringToIndex(ret.length - 1)
        c = ret.characterAtIndex(ret.length - 1)


        if (c == 46) {
            ret = ret.substringToIndex(ret.length - 1)
        }
    }
    return ret
}


abbreviateNumber(123)
abbreviateNumber(12503)
abbreviateNumber(12934203)
abbreviateNumber(12234200003)
abbreviateNumber(92234203)
abbreviateNumber(9223.3)
4
répondu coderek 2015-06-04 18:29:34

Vous pouvez utiliser cette fonction simple, l'idée est facile à comprendre

-(NSString*) suffixNumber:(NSNumber*)number
    double value = [number doubleValue];
    NSUInteger index = 0;
    NSArray *suffixArray = @[@"", @"K", @"M", @"B", @"T", @"P", @"E"];

    while ((value/1000) >= 1){
       value = value/1000;
       index++;
    }

    //3 line of code below for round doubles to 1 digit
    NSNumberFormatter *fmt = [[NSNumberFormatter alloc] init];
    [fmt setMaximumFractionDigits:1];
    NSString *valueWith1Digit = [fmt stringFromNumber:[NSNumber numberWithFloat:value]];

    NSString *svalue = [NSString stringWithFormat:@"%@%@",valueWith1Digit, [suffixArray objectAtIndex:index]];
    return svalue;
}

essai

NSLog(@"%@",[self suffixNumber:@100]);     //  100
NSLog(@"%@",[self suffixNumber:@1000]);    // 1K
NSLog(@"%@",[self suffixNumber:@10345]);   // 10.3K
NSLog(@"%@",[self suffixNumber:@10012]);   // 10K
NSLog(@"%@",[self suffixNumber:@123456]);  // 123.5K
NSLog(@"%@",[self suffixNumber:@4384324]); // 4.4M
NSLog(@"%@",[self suffixNumber:@10000000]) // 10M
3
répondu Phan Van Linh 2016-08-18 08:45:52

réponse mise à jour pour la conversion swift

extension Int {
    func abbreviateNumber() -> String {
        func floatToString(val: Float) -> String {
            var ret: NSString = NSString(format: "%.1f", val)

            let c = ret.characterAtIndex(ret.length - 1)

            if c == 46 {
                ret = ret.substringToIndex(ret.length - 1)
            }

            return ret as String
        }

        var abbrevNum = ""
        var num: Float = Float(self)

        if num >= 1000 {
            var abbrev = ["K","M","B"]

            for var i = abbrev.count-1; i >= 0; i-- {
                let sizeInt = pow(Double(10), Double((i+1)*3))
                let size = Float(sizeInt)

                if size <= num {
                    num = num/size
                    var numStr: String = floatToString(num)
                    if numStr.hasSuffix(".0") {
                        let startIndex = numStr.startIndex.advancedBy(0)
                        let endIndex = numStr.endIndex.advancedBy(-2)
                        let range = startIndex..<endIndex
                        numStr = numStr.substringWithRange( range )
                    }

                    let suffix = abbrev[i]
                    abbrevNum = numStr+suffix
                }
            }
        } else {
            abbrevNum = "\(num)"
            let startIndex = abbrevNum.startIndex.advancedBy(0)
            let endIndex = abbrevNum.endIndex.advancedBy(-2)
            let range = startIndex..<endIndex
            abbrevNum = abbrevNum.substringWithRange( range )
        }

        return abbrevNum
    }
}
2
répondu Aadi007 2015-11-18 20:55:09

Voici une version mise à jour de la réponse de Luca Iaco qui fonctionne avec Swift 4

func suffixNumber(number: NSNumber) -> String {
    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)
    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])";
}
2
répondu Josh 2017-10-18 19:42:44
extension Int {
    func abbreviateNumber() -> String {
        func floatToString(val: Float) -> String {
            var ret: NSString = NSString(format: "%.1f", val)

            var c = ret.characterAtIndex(ret.length - 1)

            if c == 46 {
                ret = ret.substringToIndex(ret.length - 1)
            }

            return ret as String
        }

        var abbrevNum = ""
        var num: Float = Float(self)

        if num >= 1000 {
            var abbrev = ["K","M","B"]

            for var i = abbrev.count-1; i >= 0; i-- {
                var sizeInt = pow(Double(10), Double((i+1)*3))
                var size = Float(sizeInt)

                if size <= num {
                    num = num/size
                    var numStr: String = floatToString(num)
                    if numStr.hasSuffix(".0") {
                        numStr = numStr.substringToIndex(advance(numStr.startIndex,count(numStr)-2))
                    }

                    var suffix = abbrev[i]
                    abbrevNum = numStr+suffix
                }
            }
        } else {
            abbrevNum = "\(num)"
            if abbrevNum.hasSuffix(".0") {
                abbrevNum = abbrevNum.substringToIndex(advance(abbrevNum.startIndex, count(abbrevNum)-2))
            }
        }

        return abbrevNum
    }
}
1
répondu Zoyt 2015-08-18 13:15:31

si vous êtes intéressé à formater le nombre d'octets, cet article de Mattt Thompson montre comment utiliser iOS / OSX builtin NSByteCountFormatter

Il ya aussi des formateursinstallés pour énergie , masse , longueur et un tas d'autres.

L'essentiel, c'est que pour la plupart des unités communes vous n'avez pas besoin d'écrire tout personnalisé code comme Apple a déjà fourni le travail fastidieux pour vous. Vérifiez leur référence en ligne pour NS [SomeUnit]Formatter, par exemple MKDistanceFormatter , NSDateIntervalFormatter ou NSDateFormatter , etc...

1
répondu verec 2016-03-02 11:09:19

j'ai utilisé la réponse de gbitaudeau pour faire cette catégorie D'Objectif C de NSNumberFormatter, que j'utilise dans notre projet ( Vero.co ). L'instance NSNumberFormatter n'a été créée qu'une seule fois pour l'ensemble du projet.

@implementation NSNumberFormatter (Abbreviation)
+ (NSString*) abbreviatedStringFromNumber:(NSNumber*) number
{
    static dispatch_once_t pred;
    static NSNumberFormatter* __abbrFormatter = nil;
    static NSArray<NSDictionary*> * __abbreviations = nil;

    dispatch_once(&pred, ^{
        __abbrFormatter = [[NSNumberFormatter alloc] init];
        __abbrFormatter.numberStyle = NSNumberFormatterDecimalStyle;
        __abbrFormatter.usesGroupingSeparator = YES;
        __abbrFormatter.allowsFloats = YES;
        __abbrFormatter.minimumIntegerDigits = 1;
        __abbrFormatter.minimumFractionDigits = 0;
        __abbrFormatter.maximumFractionDigits = 2;

        __abbreviations = @[@{@"threshold":@(0.0), @"divisor":@(1.0), @"suffix":@""},
                        @{@"threshold":@(1000.0), @"divisor":@(1000.0), @"suffix":@"K"},
                        @{@"threshold":@(1000000.0), @"divisor":@(1000000.0), @"suffix":@"M"}];
    });

    double startValue = ABS([number doubleValue]);
    NSDictionary* abbreviation = __abbreviations[0];
    for (NSDictionary* tmpAbbr in __abbreviations)
    {
        if (startValue < [tmpAbbr[@"threshold"] doubleValue])
        {
            break;
        }
        abbreviation = tmpAbbr;
    }

    double value = [number doubleValue] / [abbreviation[@"divisor"] doubleValue];
    [__abbrFormatter setLocale:[NSLocale currentLocale]]; //user might change locale while the app is sleeping
    [__abbrFormatter setPositiveSuffix:abbreviation[@"suffix"]];
    [__abbrFormatter setNegativeSuffix:abbreviation[@"suffix"]];

    return [__abbrFormatter stringFromNumber:@(value)];
}
@end

vous pouvez maintenant l'appeler comme ça

[NSNumberFormatter abbreviatedStringFromNumber:@(N)];
1
répondu user726522 2016-07-29 05:51:27

Swift-4 Doble extension - cela fonctionne très bien dans tous les cas.

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
    }
}

enter image description here

enter image description here

enter image description here

enter image description here

1
répondu KiranJasvanee 2018-04-20 06:01:21

la méthode suivante traite les nombres positifs et négatifs contrairement à la plupart des solutions ici.

Il fonctionne même pour la monnaie.

BOOL isCurrency = YES; // Make it YES / NO depending upon weather your input value belongs to a revenue figure or a normal value.
double value = XXX ; // where 'XXX' is your input value

NSString *formattedValue = @"";

int decimalPlaces = 1; // number of decimal places (precision) that you want.
float multiplier;

// Enumerate number abbreviations
NSArray *abbrevations = @[@"", @"k", @"m", @"b", @"t" ];

// Go through the array backwards, so we do the largest first
int index;
for (index = abbrevations.count-1; index >= 0; index--) {

    multiplier = pow(10, decimalPlaces);

    // Convert array index to "1000", "1000000", etc
    double size = pow(10, index*3); 

    // If the number is bigger or equal do the abbreviation
    if(size <= fabs(round(value)))
    {
        // Here, we multiply by multiplier, round, and then divide by multiplier.
        // This gives us nice rounding to a particular decimal place.
        value = round(value * multiplier / size) / multiplier;


        // We are done... stop
        break;
    }
}

if (index<0)
{
    // Note: - To handle special case where x is our input number,  -0.5 > x < 0.5
    value = 0;
    index++;
}

NSString *stringFormat = nil;
// Add the letter for the abbreviation
if (isCurrency) 
{
    if (value >=0)
    {
        stringFormat = [NSString stringWithFormat:@"$%%.%0df%@", decimalPlaces, abbrevations[index]];
    }
    else
    {
        // Note: - To take care of extra logic where '$' symbol comes after '-' symbol for negative currency.
        stringFormat = [NSString stringWithFormat:@"-$%%.%df%@", decimalPlaces, abbrevations[index]];
        value = -value;
    }
}
else
{
    stringFormat = [NSString stringWithFormat:@"%%.%0df%@", decimalPlaces, abbrevations[index]];
}

formattedValue = [NSString stringWithFormat:stringFormat, value];

sortie est comme ci-dessous

In Currency mode

'999' ---- '9.0' 
'999.9' ---- '.0k' 
'999999.9' ---- '.0m' 
'-1000.1' ---- '-.0k' 
'-0.9' ---- '-"151910920".9' 

In Number mode

'999' ---- '999.0' 
'999.9' ---- '1.0k' 
'1' ---- '1.0' 
'9999' ---- '10.0k' 
'99999.89999999999' ---- '100.0k' 
'999999.9' ---- '1.0m' 
'-1' ---- '-1.0' 
'-1000.1' ---- '-1.0k' 
'5109999' ---- '5.1m' 
'-5109999' ---- '-5.1m' 
'999999999.9' ---- '1.0b' 
'0.1' ---- '0.0' 
'0' ---- '0.0' 
'-0.1' ---- '0.0' 
'-0.9' ---- '-0.9' 

j'ai créé la méthode ci-dessus basée sur L'inspiration originale de Kyle @Begeman du lien partagé par @Pandiyan Cool. Merci à @Jeff B pour le code initial en Javascript du lien suivant. est là une façon de arrondir les chiffres dans un format facile à lire? (par exemple $ 1.1 k)

0
répondu Rajesh 2017-05-23 12:02:38

Swift 2.2 en double extension:

extension Double {

var suffixNumber : String {

    get {

        var num = self

        let sign = ((num < 0) ? "-" : "" )

        num = fabs(num)

        if (num < 1000.0){
            return "\(sign)\(num)"
        }

        let exp:Int = Int(log10(num) / 3.0 )

        let units:[String] = ["K","M","G","T","P","E"]

        let roundedNum = round(10 * num / pow(1000.0,Double(exp))) / 10

        return "\(sign)\(roundedNum)\(units[exp-1])"
    }
}
}
0
répondu Bobj-C 2016-07-01 15:48:38

version Swift 4.0 de la réponse de Phan Van Linh

private static let suffix = ["", "K", "M", "B", "T", "P", "E"]

public static func formatNumber(_ number: Double) -> String{
   var index = 0
   var value = number
   while((value / 1000) >= 1){
       value = value / 1000
       index += 1
   }
   return String(format: "%.1f%@", value, suffix[index])
}
0
répondu Bassem Qoulta 2018-05-23 09:40:39

pourquoi c'est si difficile pour vous?

cela peut être aussi simple que ceci:

-(NSString *)friendlyNumber:(long long)num{

    NSString *stringNumber;

    if (num < 1000) {
        stringNumber = [NSString stringWithFormat:@"%lld", num];

    }else if(num < 1000000){
        float newNumber = floor(num / 100) / 10.0;
        stringNumber = [NSString stringWithFormat:@"%.1fK", newNumber];

    }else{
        float newNumber = floor(num / 100000) / 10.0;
        stringNumber = [NSString stringWithFormat:@"%.1fM", newNumber];
    }
    return stringNumber;
}
-1
répondu Leo Cavalcante 2016-02-04 15:35:03