2012-04-26 12 views
8

È necessario stampare un valore float in un'area di larghezza limitata nel modo più efficiente. Sto usando un NSNumberFormatter, e ho impostato due numeri dopo il punto decimale come predefinito, in modo che quando ho un numero come 234.25 è stampato come è: 234.25. Ma quando ho 1234.25 voglio stamparlo come: 1234.3, e 11234.25 dovrebbe essere stampato 11234.Limitare sia il numero frazionario sia il numero totale di cifre durante la formattazione di un galleggiante per la visualizzazione

Ho bisogno di un massimo di due cifre dopo il punto, e un massimo di cinque cifre in generale se ho cifre dopo il punto, ma dovrebbe anche stampare più di cinque cifre se la parte intera ha più.

Non vedo la possibilità di limitare il numero totale di cifre in NSNumberFormatter. Questo significa che dovrei scrivere la mia funzione per formattare i numeri in questo modo? In tal caso, qual è il modo corretto di ottenere il conteggio delle cifre nell'intero e nelle parti frazionarie di un numero? Preferirei anche lavorare con CGFLoat, anziché con lo NSNumber per evitare conversioni di tipo extra.

risposta

0

Ecco come ho implementato questo nel mio codice. Non so quanto sia efficiente, spero non male.

Così ho creare un NSNumberFormatter globale

NSNumberFormatter* numFormatter; 

e inizializzare da qualche parte:

numFormatter=[[NSNumberFormatter alloc]init]; 

Poi ho formato numerico con la seguente funzione:

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

Codice:

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

provarla:

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

uscita:

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 lo so; è ancora un esempio, giusto? –

+0

Grazie. Questa implementazione sembra abbastanza universale, ma sono preoccupato per l'efficienza. Può essere usato qualcosa di più efficiente di NSString? O non c'è modo di contare il numero di cifre nel numero oltre al conteggio della lunghezza della stringa? Ho intenzione di fare questa conversione continuamente in ogni fotogramma di animazione durante tutto il tempo di esecuzione del programma. Non sarà difficile? – BartoNaz

+2

@BartoNaz: il logaritmo in base 10 di un numero è approssimativamente la lunghezza - 1 delle sue cifre intere: 'log10f (11123.25) -> 4.046221' –

12

Stai cercando una combinazione di "cifre significative" e "cifre della frazione massima", oltre a un comportamento di arrotondamento particolare. NSNumberFormatter è uguale all'operazione:

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

risultati:

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

bella risposta, puro obj-c. –

+0

Grazie. Questo sembra davvero semplice. Ma se ho il numero: 211234.25 restituirà 211230. Ma mi piacerebbe che restituisse 211234 in modo che arrotonda solo la parte mobile e la parte intera rimanga intoccata. È ancora possibile con NSNumberFormatter? – BartoNaz

+0

Quindi voglio che la lunghezza ottimale del mio numero stampato non sia più grande di 5 cifre. Quindi lo stampo pieno se ha <= 3 cifre intere. Se ha 4 interi e più, taglio la parte decimale. Nessuna modifica alle cifre intere. Solo l'ultima cifra può essere cambiata in base alla parte decimale. – BartoNaz

0

È questo un bug quando utilizzando maximumFractionDigits e maximumSignificantDigits insieme su NSNumberForamtter su iOS 8?

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

Funziona benissimo se uso solo maximumFractionDigits

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

NSNumberFormatter maximumFractionDigits and maximumSignificantDigits bug