2012-04-26 12 views
8

Necesito imprimir un valor flotante en el área de ancho limitado más eficientemente. Estoy usando un NSNumberFormatter, y establecí dos números después del punto decimal como el predeterminado, de modo que cuando tengo un número como 234.25 se imprime como está: 234.25. Pero cuando tengo 1234.25 quiero que se imprima como: 1234.3, y 11234.25 debe imprimirse 11234.Limitación de la cantidad fraccional y total de dígitos al formatear un flotador para mostrar

Necesito un máximo de dos dígitos después del punto, y un máximo de cinco dígitos en total si tengo dígitos después del punto, pero también debe imprimir más de cinco dígitos si la parte entera tiene más.

No veo la posibilidad de limitar el número total de dígitos en NSNumberFormatter. ¿Esto significa que debería escribir mi propia función para formatear números de esta manera? Si es así, ¿cuál es la forma correcta de obtener el recuento de dígitos en el número entero y partes fraccionarias de un número? También preferiría trabajar con CGFLoat, en lugar de NSNumber para evitar conversiones de tipo adicionales.

Respuesta

0

Así es como he implementado esto en mi código. No sé cuán eficiente es, espero que no esté mal.

lo tanto, crear un NSNumberFormatter mundial

NSNumberFormatter* numFormatter; 

e inicializar en alguna parte:

numFormatter=[[NSNumberFormatter alloc]init]; 

Entonces formato de número con la siguiente función:

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

Código:

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

probándola:

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

Salida:

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 que sé; sigue siendo un ejemplo, ¿verdad? –

+0

Gracias. Esta implementación parece bastante universal, pero me preocupa la eficiencia. ¿Se puede usar algo más eficiente que NSString? ¿O no hay forma de contar la cantidad de dígitos en el número además de contar la longitud de la cuerda? Voy a hacer esta conversión continuamente en cada cuadro de animación durante todo el tiempo de ejecución del programa. ¿No será difícil? – BartoNaz

+2

@BartoNaz: el logaritmo de base 10 de un número es aproximadamente la longitud - 1 de sus dígitos enteros: 'log10f (11123.25) -> 4.046221' –

12

Está buscando una combinación de "dígitos significativos máximos" y "dígitos de fracción máxima", junto con un comportamiento de redondeo particular. NSNumberFormatter es igual a la tarea:

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

Resultado:

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

nice answer, pure obj-c. –

+0

Gracias. Esto se ve realmente simple. Pero si tengo el número: 211234.25, devolverá 211230. Pero me gustaría que devuelva 211234 para que solo redondee la parte flotante, y la parte entera no se toque. ¿Todavía es posible con NSNumberFormatter? – BartoNaz

+0

Así que quiero que la longitud óptima de mi número impreso no sea mayor a 5 dígitos. Así que lo imprimo completo si tiene <= 3 dígitos enteros. Si tiene 4 enteros y más, corté la parte decimal. Sin cambios en los dígitos enteros. Solo el último dígito se puede cambiar de acuerdo con la parte decimal. – BartoNaz

0

Es esto un error cuando usando maximumFractionDigits y maximumSignificantDigits juntos en NSNumberForamtter en iOS 8?

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

Funciona bien si yo sólo uso maximumFractionDigits

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

NSNumberFormatter maximumFractionDigits and maximumSignificantDigits bug

Cuestiones relacionadas