8

Мне нужно напечатать значение поплавка в области с ограниченной шириной наиболее эффективно. Я использую NSNumberFormatter, и я установил два числа после десятичной точки в качестве значения по умолчанию, так что, когда у меня есть номер 234.25, он напечатан как есть: 234.25. Но когда у меня есть 1234.25, я хочу, чтобы оно было напечатано как: 1234.3, и 11234.25 должно быть напечатано 11234.Ограничение как дробного, так и общего числа цифр при форматировании поплавка для отображения

Мне нужна не более двух цифр после точки и максимум пять цифр в целом, если у меня есть цифры после точки, но она также должна печатать более пяти цифр, если целочисленная часть имеет больше.

Я не вижу возможности ограничить общее количество цифр в NSNumberFormatter. Означает ли это, что я должен написать свою собственную функцию для форматирования чисел таким образом? Если да, то каков правильный способ подсчета цифр в целочисленной и дробной частях числа? Я также предпочел бы работать с CGFLoat, а не NSNumber, чтобы избежать дополнительных преобразований типа.

ответ

0

Вот как я реализовал это в моем коде. Я не знаю, насколько он эффективен, надеюсь, неплохо.

Так создать глобальную NSNumberFormatter

NSNumberFormatter* numFormatter; 

и инициализировать его где-нибудь:

numFormatter=[[NSNumberFormatter alloc]init]; 

Затем я форматировать число с помощью следующей функции:

- (NSString*)formatFloat:(Float32)number withOptimalDigits:(UInt8)optimalDigits maxDecimals:(UInt8)maxDecimals 
{ 
    NSString* result; 
    UInt8 intDigits=(int)log10f(number)+1; 
    NSLog(@"Formatting %.5f with maxDig: %d maxDec: %d intLength: %d",number,optimalDigits,maxDecimals,intDigits); 

    numFormatter.maximumFractionDigits=maxDecimals; 
    if(intDigits>=optimalDigitis-maxDecimals) { 
     numFormatter.usesSignificantDigits=YES; 
     numFormatter.maximumSignificantDigits=(intDigits>optimalDigits)?intDigits:optimalDigits; 
    } else { 
     numFormatter.usesSignificantDigits=NO; 
    } 
    result = [numFormatter stringFromNumber:[NSNumber numberWithFloat:number]]; 

    return result; 
} 
1

Код:

#define INTPARTSTR(X) [NSString stringWithFormat:@"%d",(int)X] 
#define DECPARTSTR(X) [NSString stringWithFormat:@"%d",(int)(((float)X-(int)X)*100)] 

- (NSString*)formatFloat:(float)f 
{ 
    NSString* result; 

    result = [NSString stringWithFormat:@"%.2f",f]; 

    if ([DECPARTSTR(f) isEqualToString:@"0"]) return INTPARTSTR(f); 
    if ([INTPARTSTR(f) length]==5) return INTPARTSTR(f); 

    if ([result length]>5) 
    { 
     int diff = (int)[result length]-7; 

     NSString* newResult = @""; 

     for (int i=0; i<[result length]-diff-1; i++) 
      newResult = [newResult stringByAppendingFormat:@"%c",[result characterAtIndex:i]]; 

     return newResult; 
    } 


    return result; 
} 

тестирования:

- (void)awakeFromNib 
{ 
    NSLog(@"%@",[self formatFloat:234.63]); 
    NSLog(@"%@",[self formatFloat:1234.65]); 
    NSLog(@"%@",[self formatFloat:11234.65]); 
    NSLog(@"%@",[self formatFloat:11234]); 
} 

Выход:

2012-04-26 19:27:24.429 newProj[1798:903] 234.63 
2012-04-26 19:27:24.432 newProj[1798:903] 1234.6 
2012-04-26 19:27:24.432 newProj[1798:903] 11234 
2012-04-26 19:27:24.432 newProj[1798:903] 11234 
+1

@JacquesCousteau я знаю; это еще пример, верно? –

+0

Спасибо. Эта реализация выглядит вполне универсальной, но меня беспокоит эффективность. Может ли что-то более эффективное, чем NSString? Или нет способа подсчитать количество цифр в числе, кроме подсчета длины строки? Я буду делать это преобразование непрерывно в каждом кадре анимации в течение всего времени работы программы. Разве это не сложно? – BartoNaz

+2

@BartoNaz: Логарифм числа оснований -10 числа приблизительно равен 1 его целочисленным числам: 'log10f (11123.25) -> 4.046221' –

12

Вы ищете комбинацию «максимальных значащих цифр» и «максимальных цифр», а также особое поведение округления. NSNumberFormatter равно задаче:

float twofortythreetwentyfive = 234.25; 
float onetwothreefourtwentyfive = 1234.25; 
float eleventwothreefourtwentyfive = 11234.25; 

NSNumberFormatter * formatter = [[NSNumberFormatter alloc] init]; 
[formatter setUsesSignificantDigits:YES]; 
[formatter setMaximumSignificantDigits:5]; 
[formatter setMaximumFractionDigits:2]; 
[formatter setRoundingMode:NSNumberFormatterRoundCeiling]; 

NSLog(@"%@", [formatter stringFromNumber:[NSNumber numberWithFloat:twofortythreetwentyfive]]); 
NSLog(@"%@", [formatter stringFromNumber:[NSNumber numberWithFloat:onetwothreefourtwentyfive]]); 
NSLog(@"%@", [formatter stringFromNumber:[NSNumber numberWithFloat:eleventwothreefourtwentyfive]]); 

Результат:

2012-04-26 16: 32: 04.481 SignificantDigits [11565: 707] 234,25
2012-04-26 16:32: 04.482 SignificantDigits [11565: 707] 1234,3
2012-04-26 16: 32: 04.483 SignificantDigits [11565: 707] 11235

+0

приятный ответ, чистый obj-c. –

+0

Спасибо. Это выглядит очень просто. Но если у меня есть номер: 211234.25, он вернет 211230. Но я бы хотел, чтобы он возвращал 211234, чтобы он только округлял плавающую часть, а целочисленная часть оставалась нетронутой. Возможно ли это с помощью NSNumberFormatter? – BartoNaz

+0

Так что я хочу, чтобы оптимальная длина моего напечатанного номера не превышала 5 цифр. Поэтому я печатаю его полностью, если он имеет <= 3 целых цифры. Если имеет 4 целых числа и более, я сокращаю десятичную часть. Никаких изменений целых цифр. Только последняя цифра может быть изменена в соответствии с десятичной запятой. – BartoNaz

0

Является ли это ошибка, когда используя maximumFractionDigits и maximumSignificantDigits вместе на NSNumberForamtter на iOS 8?

 NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init]; 
     formatter.maximumFractionDigits = 2; 
     formatter.maximumSignificantDigits = 3; 
     NSLog(@"%@", [formatter stringFromNumber:@(0.3333)]); // output 0.333 expected 0.33 

Он отлично работает, если я использую только maximumFractionDigits

 NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init]; 
     formatter.maximumFractionDigits = 2; 
     NSLog(@"%@", [formatter stringFromNumber:@(0.3333)]); // output expected .33 

NSNumberFormatter maximumFractionDigits and maximumSignificantDigits bug