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;
}
Therefore, CC is written in numeric form as 200. Number. Roman Numeral. 200.
CIV Roman Numerals is 104. The Roman numerals CIV are expanded according to the place value and then converted to numeric form.
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] : @""];
}
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With