如何将罗马数字转换为NSNumer

时间:2013-02-07 22:30:27

标签: objective-c nsnumber roman-numerals

我正在制作一个具有罗马数字模式的计算器。我在模型视图中执行了操作,还有一个视图控制器。我的问题是我需要将罗马数字转换为NSNumber。有一个UILabel,视图控制器获取标签中的内容并将其设置为模型视图的操作数。有谁知道如何从标签中取出罗马数字并使其成为NSNumber?这是一些代码:

- (IBAction)digitPressed:(UIButton *)sender {


    NSString *digit = [[sender titleLabel] text];
    if (self.userIsTypingNumber) {
      [self.display setText:[self.display.text stringByAppendingString:digit]];
    } else {
        [self.display setText:digit];
        self.userIsTypingNumber = YES;
    }
}

- (IBAction)operationPressed:(UIButton *)sender {

    if (self.userIsTypingNumber) {
        if ([self isValidForRoman:self.display.text] == YES) {
            //find out what roman numeral is in the display
        } else {
        NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc]init];
        [numberFormatter setNumberStyle: NSNumberFormatterDecimalStyle];
        NSNumber *n = [numberFormatter numberFromString:self.display.text];
        [[Model singleton] setOperand:n];
        self.userIsTypingNumber = NO;
        }
    }
    NSString *operation = [[sender titleLabel] text];
    NSNumber *result = [[Model singleton] performOperation:operation];
    [self.display setText:[NSString stringWithFormat:@"%@", result]];
}

- (IBAction)clearDigitPressed:(UIButton *)sender {

    [self.display setText:@""];
}

- (IBAction)clearOperationPressed:(UIButton *)sender {

    [[Model singleton] performOperation:nil];
    [self.display setText:@""];
}

- (IBAction)changeNumeralType:(id)sender {

    switch ([sender selectedSegmentIndex]) {
        case 0:
        {            
            [self.button1 setTitle:@"1" forState:UIControlStateNormal];
            [self.button2 setTitle:@"2" forState:UIControlStateNormal];
            [self.button3 setTitle:@"3" forState:UIControlStateNormal];
            [self.button4 setTitle:@"4" forState:UIControlStateNormal];
            [self.button5 setTitle:@"5" forState:UIControlStateNormal];
            [self.button6 setTitle:@"6" forState:UIControlStateNormal];
            [self.button7 setTitle:@"7" forState:UIControlStateNormal];
            [self.button8 setTitle:@"8" forState:UIControlStateNormal];
            [self.button9 setTitle:@"9" forState:UIControlStateNormal];
            [self.button0 setTitle:@"0" forState:UIControlStateNormal];
        } break;

        case 1:
        {
            [self.button1 setTitle:@"L" forState:UIControlStateNormal];
            [self.button2 setTitle:@"C" forState:UIControlStateNormal];
            [self.button3 setTitle:@"D" forState:UIControlStateNormal];
            [self.button4 setTitle:@"I" forState:UIControlStateNormal];
            [self.button5 setTitle:@"V" forState:UIControlStateNormal];
            [self.button6 setTitle:@"X" forState:UIControlStateNormal];
            [self.button7 setTitle:@"" forState:UIControlStateNormal];
            [self.button8 setTitle:@"" forState:UIControlStateNormal];
            [self.button9 setTitle:@"" forState:UIControlStateNormal];
            [self.button0 setTitle:@"M" forState:UIControlStateNormal];

        } break;

    }
}

- (BOOL)isValidForRoman:(NSString *)text
{
    NSString *romanRegex = @"^(?=.)(?i)M*(D?C{0,3}|C[DM])(L?X{0,3}|X[LC])(V?I{0,3}|I[VX])$";
    NSPredicate *romanTest = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", romanRegex];
    return ([romanTest evaluateWithObject:text]);
}

3 个答案:

答案 0 :(得分:2)

以下是一些可以帮助您的资源:

Roman Numbers Convert - 这个可能是两者中较好的一个,因为这有前向/后向翻译

pzearfoss / NSNumber-RomanNumerals - 这是一个简单的类别;但是,它只将NSNumber转换为Roman Numeral。你可以调整它来反过来。

答案 1 :(得分:1)

你可以尝试这个功能

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

答案 2 :(得分:1)

刚写了一篇,因为我之前见过的所有内容都有点奇怪,所以欢迎你试试:https://github.com/shoumikhin/RomanNumeral

//==============================================================================
@implementation NSNumber (RomanNumeral)
//------------------------------------------------------------------------------
- (NSString *)encodeRomanDigit:(NSInteger)value one:(NSString *)one five:(NSString *)five ten:(NSString *)ten
{
    switch (value)
    {
        case 1 :

            return [NSString stringWithFormat:@"%@", one];

        case 2 :

            return [NSString stringWithFormat:@"%@%@", one, one];

        case 3 :

            return [NSString stringWithFormat:@"%@%@%@", one, one, one];

        case 4 :

            return [NSString stringWithFormat:@"%@%@", one, five];

        case 5 :

            return [NSString stringWithFormat:@"%@", five];

        case 6 :

            return [NSString stringWithFormat:@"%@%@", five, one];

        case 7 :

            return [NSString stringWithFormat:@"%@%@%@", five, one, one];

        case 8 :

            return [NSString stringWithFormat:@"%@%@%@%@", five, one, one, one];

        case 9 :

            return [NSString stringWithFormat:@"%@%@", one, ten];
    }

    return @"";
}
//------------------------------------------------------------------------------
- (NSString *)encodeRomanDigit:(NSInteger)value withDigitNumber:(NSUInteger)digitPosition
{
    switch (digitPosition)
    {
        case 0 :

            return [self encodeRomanDigit:value one:@"I" five:@"V" ten:@"X"];

        case 1 :

            return [self encodeRomanDigit:value one:@"X" five:@"L" ten:@"C"];

        case 2 :

            return [self encodeRomanDigit:value one:@"C" five:@"D" ten:@"M"];

        case 3 :

            return [self encodeRomanDigit:value one:@"M" five:@"" ten:@""];
    }

    return @"";
}
//------------------------------------------------------------------------------
- (NSString *)romanNumeralStringValue
{
    NSMutableString *ret = @"".mutableCopy;
    NSUInteger value = self.unsignedIntegerValue;
    NSUInteger base = 10;
    NSUInteger digitPosition = 0;
    NSUInteger const ROMAN_NUMBER_MAX = 4000;

    if (value < ROMAN_NUMBER_MAX)
      do
      {
          [ret insertString:[self encodeRomanDigit:value % base withBase:digitPosition] atIndex:0];
          digitPosition++;
      }
      while (value /= base);

    return ret;
}
//------------------------------------------------------------------------------
@end
//==============================================================================
@implementation NSString (RomanNumeral)
//------------------------------------------------------------------------------
- (NSInteger)decodeRomanDigit:(char)romanDigit
{
    switch (romanDigit)
    {
        case 'I' :
        case 'i' :

            return 1;

        case 'V' :
        case 'v' :
        case 'U' :
        case 'u' :

            return 5;

        case 'X' :
        case 'x' :

            return 10;

        case 'L' :
        case 'l' :

            return 50;

        case 'C' :
        case 'c' :

            return 100;

        case 'D' :
        case 'd' :

            return 500;

        case 'M' :
        case 'm' :

            return 1000;
    }

    return 0;
}
//------------------------------------------------------------------------------
- (NSInteger)romanNumeralValue
{
    NSInteger ret = 0;
    NSUInteger length = self.length;
    unichar buffer[length];

    [self getCharacters:buffer range:NSMakeRange(0, length)];

    for (int i = 0; i < length; ++i)
    {
        NSInteger current = [self decodeRomanDigit:buffer[i]];
        NSInteger next = i + 1 < length ? [self decodeRomanDigit:buffer[i + 1]] : 0;

        if (next > current)
        {
            ret += next - current;
            i++;
        }
        else
            ret += current;
    }

    return ret;
}
//------------------------------------------------------------------------------
@end
//==============================================================================