objective-ciosnsnumberformatter

How do I force a sign-character on the output of an NSNumberFormatter


I want to use a number formatter to generate my output, so the number is automatically formatted for the user's locale, but I want it to work like "%+.1f" does in printf(), that is always have a sign specified.

NSNumberFormatter *nf = [[NSNumberFormatter alloc] init];
nf.numberStyle = NSNumberFormatterDecimalStyle;
nf.maximumFractionDigits = 1;

double val = 3.1234;
label.text = [NSString stringWithFormat: @"XXX %@ XXX", [nf stringFromNumber: [NSNumber numberWithDouble: val]]];

I want the label to come out "XXX +3.1 XXX" in the US and the appropriate but equivalent string for any other location. The only things I can find are setPositiveFormat: and setPositivePrefix:.

But I don't want to set the format since I don't know how to format numbers in other countries; I don't know if a plus-sign is used to designate a positive number in Arabic or Russian or some culture I have not thought of. I do know, for example, that decimal points, commas, spaces, etc., all have different meanings in European countries compared to the U.S. - Could the same be true for +/- signs?

What I do currently is:

label.text = [NSString stringWithFormat: @"XXX %s%@ XXX", (val < 0) ? "" : "+",
    [nf stringFromNumber: [NSNumber numberWithDouble: val]]];

But this presumes that '+' and '-' are correct for all formats.

I'm sure it must be there since it is a standard formatting thing that has been in printf() since the dark ages...


Solution

  • How about this:

    NSNumberFormatter *nf = [[NSNumberFormatter alloc] init];
    nf.numberStyle = NSNumberFormatterDecimalStyle;
    nf.maximumFractionDigits = 1;
    
    double val = 3.1234;
    NSString *sign = (val < 0) ? [nf minusSign] : [nf plusSign];
    NSString *num = [nf stringFromNumber:@(abs(val))]; // avoid double negative
    label.text = [NSString stringWithFormat: @"XXX %@%@ XXX", sign, num];
    

    You may need to check to see if num has the sign prefix or not so it isn't shown twice.

    Edit: After some playing around, it has been determined, for the "Decimal" style, that no current locale uses a positivePrefix. No current locale uses a plusSign other than the standard + character. No current locale uses a negativePrefix that is different than minusSign. No current locale uses either positiveSuffix or negativeSuffix.

    So an easier approach would be to do:

    NSNumberFormatter *nf = [[NSNumberFormatter alloc] init];
    nf.numberStyle = NSNumberFormatterDecimalStyle;
    nf.maximumFractionDigits = 1;
    [nf setPositivePrefix:[nf plusSign]];
    [nf setNegativePrefix:[nf minusSign]];
    
    label.text = [nf stringFromNumber:@(val)];