罗马到十进制转换

时间:2011-03-10 02:55:34

标签: c++ recursion roman-numerals

您对此代码有何看法?这是最好的方式吗?有什么改进吗?

Roman.h

#ifndef ROMAN_H
#define ROMAN_H

#include <string>

#include <map>

typedef unsigned long int UL_I;
typedef std::map< std::string, UL_I, std::less< std::string > > Map;

class Roman_Number
{
public:
  //Constructor
  Roman_Number( std::string );

  void Convert_to_decimal();

  UL_I get_Decimal() const;
  std::string get_Roman() const;

private:
  std::string s_roman_number;
  UL_I d_number;

  Map pairs;
  Map pairs_substracting;

  //Utilitaries functions
  void _validate_();
  void _initilize_pairs_()
  {
    pairs.insert( Map::value_type( "I", 1 ) );
    pairs_substracting.insert( Map::value_type ( "IV", 4 ) );
    pairs.insert( Map::value_type( "V", 5 ) );
    pairs_substracting.insert( Map::value_type( "IX", 9 ) );
    pairs.insert( Map::value_type( "X", 10 ) );
    pairs_substracting.insert( Map::value_type( "XL", 40 ) );
    pairs.insert( Map::value_type( "L", 50 ) );
    pairs_substracting.insert( Map::value_type( "XC", 90 ) );
    pairs.insert( Map::value_type( "C", 100 ) );
    pairs_substracting.insert( Map::value_type( "CD", 400 ) );
    pairs.insert( Map::value_type( "D", 500 ) );
    pairs_substracting.insert( Map::value_type( "CM", 900 ) );  
  }
  UL_I _recursive_convert( std::string );
};

#endif

Roman.cpp

#include <iostream>

#include "Roman.h"

void Roman_Number::_validate_()
{
  std::cout << "Validating" << std::endl;

}

Roman_Number::Roman_Number(std::string r_number )
{
  _initilize_pairs_();
  s_roman_number = r_number;
  d_number = 0;
}

void Roman_Number::Convert_to_decimal()
{
  std::string s_aux = s_roman_number;
  d_number = _recursive_convert( s_aux );
}

UL_I Roman_Number::_recursive_convert( std::string new_roman )
{
  if( new_roman == "" )
    return 0;
  if( pairs_substracting.find( new_roman.substr( 0 , 2 ) ) != pairs_substracting.end() )
     return pairs_substracting[new_roman.substr( 0, 2 )] + 
        _recursive_convert( new_roman.erase( 0, 2) );
  else
     return pairs[new_roman.substr( 0, 1 )] + _recursive_convert( new_roman.erase( 0, 1 ) );
}

UL_I Roman_Number::get_Decimal() const
{
  return d_number;
}

std::string Roman_Number::get_Roman() const
{
  return s_roman_number;
}

的main.cpp

#include <iostream>

#include "Roman.h"

int main() {
  Roman_Number R_N( "XIL" );
  R_N.Convert_to_decimal();
  std::cout << R_N.get_Decimal();
  return 0;
}

3 个答案:

答案 0 :(得分:7)

这个怎么样? http://codepad.org/mJ05BldC

#include <stdio.h>

int main( void ) {
  const char* s = "MCDXLIV";
  int x = 0; // result

  int j,m=0; // max used digit
  const char* p=s, *q; while(*p) ++p;
  for( --p; p>=s; p-- ) for( q="IVXLCDM",j=0; *q; q++,j++ ) if( *p==*q )
    x += ((j>=m)?m=j,1:-1) * (1+j%4/2*9) * (1+j/4*99) * (1+j%2*4);

  printf( "s=%s x=%i\n", s, x );
}

答案 1 :(得分:1)

给出

public static final String romanNums = "IVXLCDM";

public static void main(String[] args) {
    Scanner console = new Scanner(System.in);
    String input = console.nextLine();

    int arabInt = 0;
    for (int i = 0; i < romanNums.length(); i++) {
        for (int j = 0; j < input.length(); j++) {
           if (input.substring(j, j + 1).equals(romanNums.substring(i, i + 1))) {
              arabInt += convertRomToNum(i);
              if (j > 0 && romanNums.indexOf(input.substring(j, j + 1)) > romanNums.indexOf(input.substring(j - 1, j))) {
                 arabInt -= 2 * convertRomToNum(romanNums.indexOf(input.substring(j - 1, j)));
              }
           }
    } 
  // AFTER OBSERVING PATTERN: 1, 5, 10, 50, 100, 500, 1000; AND ASSOCIATING INDEXES 
  // OF EACH ROMAN LETTER WITH CORRESPONDING NUMBER IN SEQUENCE ABOVE

public static int convertRomToNum(int i)  {    
    int numBehindLetter = (int) (Math.pow(2, Math.floor(i / 2)) * Math.pow(5, Math.ceil(i / 2.)));
    return numBehindLetter;
}

1 = 5 ^ 0 * 2 ^ 0; 5 = 5 ^ 1 * 2 ^ 0; 10 = 5 ^ 1 * 2 ^ 0; 50 = 5 ^ 2 * 2 ^ 1; 100 = 5 ^ 2 * 2 ^ 2; 500 = 5 ^ 3 * 2 ^ 2; 1000 = 5 ^ 3 * 2 ^ 3等。这就是我使用'floor'和'ceil'功能的原因。

答案 2 :(得分:0)

介于复杂和可读之间......

int convRomanToInt(string roman) {

    char[] symbol = {  'M', 'D', 'C', 'L', 'X','V','I' };
    int[]  weight = { 1000, 500, 100,  50,  10, 5 , 1  };

    int res = 0, rom = 0, num = 0;

    while (rom < roman.Length){     
        if (roman[rom] == symbol[num]){
            res += weight[num];
            rom++;
        } else if (rom < roman.Length-1 && roman[rom+1] == symbol[num]){
            res -= weight[(num&~1)+2];
            rom++;
        } else {
            num++;
        }      
    }

    return res;
}