Objective C Number to Roman Numerals
Asked Answered
P

3

6

I've been searching forever for some sample code on convert from a number to roman numerals in objective c. Anyone know where I can find a good example?

Update:

Nevermind, found a PHP function that does what I want and ported it. Seems to work fine so far.

-(NSString*)numberToRomanNumerals:(int)num{

    if (num < 0 || num > 9999) { return @""; } // out of range



    NSArray *r_ones = [[NSArray alloc]initWithObjects:@"I", @"II", @"III", @"IV", @"V", @"VI", @"VII", @"VIII",@"IX",nil];
    NSArray *r_tens = [[NSArray alloc]initWithObjects:@"X", @"XX", @"XXX", @"XL", @"L", @"LX", @"LXX",@"LXXX", @"XC",nil];
    NSArray *r_hund = [[NSArray alloc]initWithObjects:@"C", @"CC", @"CCC", @"CD", @"D", @"DC", @"DCC",@"DCCC", @"CM",nil];
    NSArray *r_thou = [[NSArray alloc]initWithObjects:@"M", @"MM", @"MMM", @"MMMM", @"MMMMM", @"MMMMMM",@"MMMMMMM",
               @"MMMMMMMM", @"MMMMMMMMM",nil];


    int ones = num % 10;
    int tens = (num - ones) % 100;
    int hundreds = (num - tens - ones) % 1000;
    int thou = (num - hundreds - tens - ones) % 10000;


    tens = tens / 10;
    hundreds = hundreds / 100;
    thou = thou / 1000;

    NSString *rnum=@"";

    if (thou) { rnum = [rnum stringByAppendingString:[r_thou objectAtIndex:thou-1]]; }
    if (hundreds) { rnum = [rnum stringByAppendingString:[r_hund objectAtIndex:hundreds-1]];    }
    if (tens) { rnum = [rnum stringByAppendingString:[r_tens objectAtIndex:tens-1]]; }
    if (ones) { rnum = [rnum stringByAppendingString:[r_ones objectAtIndex:ones-1]]; }

    [r_ones release];
    [r_tens release];
    [r_hund release];
    [r_thou release];

    return rnum;
}
Procathedral answered 9/5, 2011 at 20:17 Comment(0)
E
1

Is this homework I wonder?

The algorithm for the conversion this is just a simple "reduce number, build up string" iteration of some sort and you only need basic math, comparison and string operations.

Go to Computer Algorithms where you will find various algorithms discussed and presented in VB - it is not hard to figure out the VB even if you don't know the language.

Eleonoreeleoptene answered 9/5, 2011 at 20:48 Comment(1)
Thanks, looks like less code than what I came up with, I'll try porting it instead.Procathedral
A
2

Here is the implementation of a formatter I created. It loops through a list of the different possible numbers, so it is extremely simple to modify. Right now it only converts an integer to a string, but I will update this if I implement the opposite direction.

static unsigned majorIntValues[] = {1000,100,10,1,0};
#define numMajorIntValues (sizeof(majorIntValues) / sizeof(unsigned))
static char majorCharValues[] = {'M','C','X','I','N'};
#define numMajorCharValues (sizeof(majorCharValues) / sizeof(char))
static unsigned intValues[] = {1000,500,100,50,10,5,1};
#define numIntValues (sizeof(intValues) / sizeof(unsigned))
static char charValues[] = {'M','D','C','L','X','V','I'};
#define numCharValues (sizeof(charValues) / sizeof(char))

@implementation RomanNumeralFormatter

- (NSString *)stringForObjectValue:(id)number {
    if(![number respondsToSelector:@selector(unsignedIntegerValue)]) return @"0";
    NSUInteger value = [number unsignedIntegerValue];
    if(value == 0) return @"N";
    NSMutableString *string = [NSMutableString new];
    uint8_t i,j;
    for(i = 0, j = 0; value && i < numIntValues; ++i) {
        while(intValues[i] <= majorIntValues[j]) ++j;
        while(value >= intValues[i]) {
            [string appendFormat:@"%c",charValues[i]];
            value -= intValues[i];
        }
        if(value >= (intValues[i] - majorIntValues[j])) {
            [string appendFormat:@"%c%c",majorCharValues[j],charValues[i]];
            value -= (intValues[i] - majorIntValues[j]);
        }
    }
    return [string autorelease];
}
- (NSAttributedString *)attributedStringForObjectValue:(id)anObject withDefaultAttributes:(NSDictionary *)attributes {
    return [[[NSAttributedString alloc] initWithString:[self stringForObjectValue:anObject]
                                            attributes:attributes] autorelease];
}

- (BOOL)getObjectValue:(id *)anObject forString:(NSString *)string errorDescription:(NSString **)error {
    if(error) *error = @"Decoding roman numerals is currently unsupported";
    return NO;
}

@end
Authorize answered 9/5, 2011 at 21:16 Comment(0)
Q
2

Just a bit shorter and optimized, based on the first algorithm

+(NSString*)romain:(int)num {
    if (num < 0 || num > 9999) { return @""; } // out of range

    NSArray *r_ones = [NSArray arrayWithObjects:@"I", @"II", @"III", @"IV", @"V", @"VI", @"VII", @"VIII", @"IX", nil];
    NSArray *r_tens = [NSArray arrayWithObjects:@"X", @"XX", @"XXX", @"XL", @"L", @"LX", @"LXX",@"LXXX", @"XC", nil];
    NSArray *r_hund = [NSArray arrayWithObjects:@"C", @"CC", @"CCC", @"CD", @"D", @"DC", @"DCC",@"DCCC", @"CM", nil];
    NSArray *r_thou = [NSArray arrayWithObjects:@"M", @"MM", @"MMM", @"MMMM", @"MMMMM", @"MMMMMM", @"MMMMMMM", @"MMMMMMMM", @"MMMMMMMMM", nil];
// real romans should have an horizontal   __           ___           _____
// bar over number to make x 1000: 4000 is IV, 16000 is XVI, 32767 is XXXMMDCCLXVII...

    int thou = num / 1000;
    int hundreds = (num -= thou*1000) / 100;
    int tens = (num -= hundreds*100) / 10;
    int ones = num % 10; // cheap %, 'cause num is < 100!

    return [NSString stringWithFormat:@"%@%@%@%@",
        thou ? [r_thou objectAtIndex:thou-1] : @"",
        hundreds ? [r_hund objectAtIndex:hundreds-1] : @"",
        tens ? [r_tens objectAtIndex:tens-1] : @"",
        ones ? [r_ones objectAtIndex:ones-1] : @""];
}
Quiff answered 8/2, 2014 at 7:59 Comment(0)
E
1

Is this homework I wonder?

The algorithm for the conversion this is just a simple "reduce number, build up string" iteration of some sort and you only need basic math, comparison and string operations.

Go to Computer Algorithms where you will find various algorithms discussed and presented in VB - it is not hard to figure out the VB even if you don't know the language.

Eleonoreeleoptene answered 9/5, 2011 at 20:48 Comment(1)
Thanks, looks like less code than what I came up with, I'll try porting it instead.Procathedral

© 2022 - 2024 — McMap. All rights reserved.