Formatting a number with thousands separator and 10 digit limitation in Xcode CS193P

Discussion in 'iOS Programming' started by GuitarBoy18, Aug 21, 2013.

  1. GuitarBoy18 macrumors newbie

    Joined:
    Aug 21, 2013
    #1
    I want to format a number like 1,000,000,000 instead of 1000000000 in CS193P calculator based my version of calculator app. I did some research about similar question and other CS193P based calculators. Then I found answers that could be an answer of my question like these article.

    - How to add commas to numbers? (MacRumors Forums)
    http://forums.macrumors.com/showthread.php?t=916491

    - NSNumberFormatter IOS Calculator display (Stack Overflow)
    http://stackoverflow.com/questions/18025635/nsnumberformatter-ios-calculator-display

    - NSNumberFormatter Class Reference (iOS Developer Library)
    https://developer.apple.com/library...umberFormatter_Class/Reference/Reference.html

    - NumberFormatters Data Formatting Guid (iOS Developer Library)
    https://developer.apple.com/library...rmatting/Articles/dfNumberFormatting10_4.html

    But problem is I don't know how it convert into my code.
    Please give me an example or correct my code would be really appreciate.

    How to formatting a number with thousands separator?

    How to set limitation to display like display able to show up to 10 digits of number including floating point?

    For example some number like 1,000.123456789, I want to show that number like 1,000.123457 instead of 1,000.123456789 or 1,000.123456 based on condition something like round up if the number is bigger than 10 digit including floating numbers.

    My code is
    Code:
    - (IBAction)digitPressed:(UIButton *)sender {
        error.text = nil;
    
        NSString *digit = [[sender titleLabel] text];
        if (userIsInTheMiddleOfTypingANumber) {
            [display setText:[[display text] stringByAppendingString:digit]];
        } else {
            [display setText:digit];
            userIsInTheMiddleOfTypingANumber = YES;
        }
        NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
        [formatter setPositiveFormat:@",###"];
    }
    
     
  2. ArtOfWarfare, Aug 21, 2013
    Last edited: Aug 21, 2013

    ArtOfWarfare macrumors G3

    ArtOfWarfare

    Joined:
    Nov 26, 2007
    #2
    Probably the easiest way to enforce a ten digit limit would be to have an iVar counter that counts the number of times a digit is entered and ignores when the user attempts to enter more than 10 digits

    As for the formatter... I'm not familiar with it so I'm just looking at the class reference and trying to help... I'm not sure if it's what is best for this situation or not. I think I would possibly just write a for loop that runs backwards over the string looking for the . and , characters, then skipping over 3 chars, checking if the next one is a , and adding one if it's not. Something like that.

    I'm sure other people have other, probably better solutions.
     
  3. idelovski, Aug 21, 2013
    Last edited: Aug 21, 2013

    idelovski macrumors regular

    Joined:
    Sep 11, 2008
    #3
    This is what I wrote at some point when I needed numbers. Hope you'll find it usefull:

    Code:
    // -----------------------------------------------------------------------------
    #pragma mark - Numbers
    // -----------------------------------------------------------------------------
    
    + (NSString *)formatCurrencyValue:(double)value
    {
       return ([self formatDecimalValue:value
                          decimalPlaces:2
                           showCurrency:NO
                                  group:YES
                               showZero:NO]);
    }
    
    + (NSString *)formatCurrencyValue:(double)value
                         showCurrency:(BOOL)showCurrency
                             showZero:(BOOL)showZero
    {
       return ([self formatDecimalValue:value
                          decimalPlaces:2
                           showCurrency:showCurrency
                                  group:YES
                               showZero:showZero]);
    }
    
    + (NSString *)formatDecimalValue:(double)value
                       decimalPlaces:(int)decPlc
                        showCurrency:(BOOL)showCurrency
                               group:(BOOL)groupByThousend
                            showZero:(BOOL)showZero
    {
       NSNumberFormatter  *numberFormatter = [[NSNumberFormatter alloc] init];
    
       [numberFormatter setFormatterBehavior:NSNumberFormatterBehavior10_4];
       // [numberFormatter setCurrencySymbol:@"$"];
       [numberFormatter setNumberStyle:NSNumberFormatterDecimalStyle];  // NSNumberFormatterCurrencyStyle
       if (groupByThousend)
          [numberFormatter setUsesGroupingSeparator:YES];
    
       [numberFormatter setMinimumFractionDigits:decPlc];
       [numberFormatter setMaximumFractionDigits:decPlc];
    
       [numberFormatter setLocale:[NSLocale currentLocale]];
    
       NSNumber  *c = [NSNumber numberWithFloat:value];
    
       // NSLog (@"Currency symbol   : %@", numberFormatter.currencySymbol);
       // NSLog (@"Currency separator: %@", numberFormatter.currencyGroupingSeparator);
    
       NSLog (@"Currency padding: %d", numberFormatter.paddingPosition);
    
    
       NSString  *retStr = [numberFormatter stringFromNumber:c];
    
       if (!showZero && ([retStr isEqual:@"0,00"] || [retStr isEqual:@"0.00"]))
          return (@"");
    
       if (showCurrency)
          return ([NSString stringWithFormat:@"%@ %@", retStr, numberFormatter.currencySymbol]);
    
       return (retStr);
    }
    Notice that the code is for ARC and that the currency symbol is placed after the value. Feel free to change anything and experiment.
     
  4. GuitarBoy18 thread starter macrumors newbie

    Joined:
    Aug 21, 2013
    #4
    Thanks for your reply and sample code!

    I edit my code something like this. It's no error but "," doesn't appear on calculator display. I think these numberFormatter things are yet not hocked up with text. If you can correct this code, that would be awesome.

    Code:
        - (IBAction)digitPressed:(UIButton *)sender {
        error.text = nil;
            
            NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
            [numberFormatter setUsesGroupingSeparator:YES];
            [numberFormatter setGroupingSize:3];
            [numberFormatter setGroupingSeparator:@","];
            [numberFormatter setMaximumFractionDigits:10];
        
            NSString *digit = [[sender titleLabel] text];
        
            //NSLog(@"digit pressed = %@", digit);
            
            if (userIsInTheMiddleOfTypingANumber) {
                [display setText:[[display text] stringByAppendingString:digit]];
            } else {
                [display setText:digit];
                userIsInTheMiddleOfTypingANumber = YES;
                
            }
            
        }
    
    Thanks!
     
  5. idelovski macrumors regular

    Joined:
    Sep 11, 2008
    #5
    You're not really using the formatter.

    Can't say what is userIsInTheMiddleOfTypingANumber, but when you append the last digit, put somewhere these two lines:

    Code:
       NSNumber  *c = [numberFormatter numberFromString:display.text];
    
       display.text = [numberFormatter stringFromNumber:c];
    
     
  6. GuitarBoy18 thread starter macrumors newbie

    Joined:
    Aug 21, 2013
    #6
    It's works!!

    Thanks your help my friend! I put those lines in my code like this:

    Code:
    - (IBAction)digitPressed:(UIButton *)sender {
        error.text = nil;
        
        NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
        [numberFormatter setNumberStyle:NSNumberFormatterDecimalStyle];
        
        NSString *digit = [[sender titleLabel] text];
        //NSLog(@"digit pressed = %@", digit);
        
    
        if (userIsInTheMiddleOfTypingANumber) {
            [display setText:[[display text] stringByAppendingString:digit]];
            
            
            NSNumber  *c = [numberFormatter numberFromString:display.text];
            display.text = [numberFormatter stringFromNumber:c];
            
            
        } else {
            [display setText:digit];
            userIsInTheMiddleOfTypingANumber = YES;
            
        }
    }
    
    And a number like 1000 convert to 1,000!! This is awesome!
    But when I enter 5th digit right after 1,000, display goes to empty. Then I notice display has got limitation up to 4 digit available somehow.

    Now I'm searching how to figure it out. At same time I would like to continue to receiving your help or hint, if you have time for it.

    BTW, custom class "userIsInTheMiddoleOfTypingANumber" is set for erase 0 thats shows up on display from the begging in my understanding.

    Thank you again. This is certainly moving forward by your help.
     
  7. GuitarBoy18, Aug 23, 2013
    Last edited: Aug 24, 2013

    GuitarBoy18 thread starter macrumors newbie

    Joined:
    Aug 21, 2013
    #7
    Now display became able to show bigger than 4 digit with thousands separator but..

    Here is my update.

    Display now able to show number with thousands separator which enter by digitPressed action. Then I want to same number format for operationPressed action. I've add those lines to operationPressed section. But this time when I pressed operation button after enter number by pressed digit button, numbers after thousands separator erased. For example I enter number like 100000 and then display shows number as 100,000. After that I press operation button like +, the number become 100 instead of 100,000 and then enter some number like 1 and equal button, display shows result as 101.

    Code:
    - (IBAction)operationPressed:(UIButton *)sender
    {
        //
        NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
        [numberFormatter setNumberStyle:NSNumberFormatterDecimalStyle];
        //
    
        if(userIsInTheMiddleOfTypingANumber){
            self.model.operand = [display.text doubleValue];
            userIsInTheMiddleOfTypingANumber = NO;
        }
    
        NSString *operation = [[sender titleLabel] text];
        [self.model performOperation:operation];
        NSNumber  *c = [numberFormatter numberFromString:display.text];
        display.text = [numberFormatter stringFromNumber:c];
        display.text = [NSString stringWithFormat:@"%.12g", self.model.operand];
    
    I think I don't wired up numberFormatter and operand yet. But problem is I don't know how to do it. I'm keep trying figure it out now. But if anyone knows how to do it or find problem in these code, please let me know it.
    Thanks,
     
  8. idelovski macrumors regular

    Joined:
    Sep 11, 2008
    #8
    You can't use [display.text doubleValue] sometimes and formatter other times. You must use formatter for all conversions from text to numbesrs and back.
     
  9. GuitarBoy18 thread starter macrumors newbie

    Joined:
    Aug 21, 2013
    #9
    Thanks!

    Thanks for your comment. That's make sense. I really don't understand C syntax yet. So I'm searching sample code. If I can't find something like that, better would learn syntax.
     
  10. ArtOfWarfare macrumors G3

    ArtOfWarfare

    Joined:
    Nov 26, 2007
    #10
    Isn't this a gross violation of MVC?

    Shouldn't he have a number variable (say, a double?) which is directly modified when the keys are pressed and then separately have an NSString which is displayed and whose value is always the double run through a formatter?
     
  11. GuitarBoy18 thread starter macrumors newbie

    Joined:
    Aug 21, 2013
    #11
    Oh snap!

    Yeah number value is double. And snap! That is calculator model. I don't put number formatter in my calculator model itself yet. I'm gonna do that.
     
  12. GuitarBoy18, Aug 30, 2013
    Last edited: Sep 2, 2013

    GuitarBoy18 thread starter macrumors newbie

    Joined:
    Aug 21, 2013

Share This Page