3

I have a test due in about four hours and one of the questions asks us to convert a user-inputed integer up to 100 into a roman numeral. I think my code is very close (I found a youtube video that I sort of used as a guide) but alas my code simply will not work :(. Can anyone spot the errors? EDIT: Ah sry sry sry, the problem is that when it compiles, it gives no Roman numerals. As in I enter a value and it gives me a blank.

    #include "stdafx.h"
#include <iostream>
#include <string>
    using namespace std;


int main()
{
    string romnum;
    int input;
    int num;
    cout << "Type in an integer: ";
    cin >> input;
    if(( input >= 101) || (input <= 0)) // <-- this is the upper bound
    {
        cout << "\n INVALID INPUT";
    }
    else
    {
        if(input = 100)
        {
            romnum + 'C';

        }
        input %= 100; // gets the remainder after dividing by 100

        if(input <= 10)
        {
            num = (input/10); // now we are dealing with number in 10s place
            if(num == 9)
            {
                romnum += "XC";
            }
            else if(num >= 5)
            {
                romnum += 'L';

                for(int i=0; i < num - 5;i++)
                {
                    romnum += 'X';
                }
            }
            else if(num == 4)
            {
                romnum += "XL";
            }
            else if(num >= 1)
            {
                for(int i=0; i>num; i++)
                {
                    romnum += 'X';
                }
                input %= 10;
            }
            if(num >= 1)
            {
                num = input; //  now we are dealing with number in ones place
                if(num == 9)
                {
                    romnum += "IX";
                }
                else if(num >= 5)
                {
                    romnum += 'V';
                    for(int i=0; i < num - 5; i++)
                    {
                        romnum += 'I';
                    }
                }
                else if(num == 4)
                {
                    romnum += "IV";
                }
                else if(num >= 1)
                {
                    for(int i = 0; i < num; i++)
                    {
                        romnum += 'I';
                    }
                }
        cout << "The Roman Numeral is: " << romnum;

            }
        }



        cout << "The Roman Numeral is: " << romnum;
    }
    int f;
    cin >> f;
    return 0;
}

enter code here
Jim Slatten
  • 41
  • 1
  • 1
  • 6
  • Just google `c++ integer to roman numeral`. – Itay Oct 09 '13 at 07:50
  • 2
    *How* doesn't it work? Doesn't it compile? If so then provide the compilation errors. Doesn't it run as it should? Then present example input and actual and wanted output. Please read [the Stack Overflow question checklist](http://meta.stackexchange.com/questions/156810/stack-overflow-question-checklist), it will help you ask better questions. – Some programmer dude Oct 09 '13 at 07:51
  • If you know that the value is 100 or less, the simplest solution is just to use a table. (But of course, I doubt that this is what your instructor is looking for.) – James Kanze Oct 09 '13 at 08:14
  • You could also print the number in decimal, and have 3 tables to convert each individual digit. These tables are quite similar (7 = VII, 70 = LXX, the pattern should be clear), so you can do even smarter things. And that solution would easily be extended to a thousand. – MSalters Oct 09 '13 at 11:30

9 Answers9

12

From http://rosettacode.org/wiki/Roman_numerals/Encode#C.2B.2B

std::string to_roman(unsigned int value)
{
    struct romandata_t { unsigned int value; char const* numeral; };
    const struct romandata_t romandata[] =
    {
        {1000, "M"}, {900, "CM"},
        {500, "D"}, {400, "CD"},
        {100, "C"}, { 90, "XC"},
        { 50, "L"}, { 40, "XL"},
        { 10, "X"}, { 9, "IX"},
        { 5, "V"}, { 4, "IV"},
        { 1, "I"},
        { 0, NULL} // end marker
    };

    std::string result;
    for (const romandata_t* current = romandata; current->value > 0; ++current)
    {
        while (value >= current->value)
        {
            result += current->numeral;
            value -= current->value;
        }
    }
    return result;
}
Jarod42
  • 203,559
  • 14
  • 181
  • 302
5

This code will convert integers (less than 3999) to Roman Numerals.

string int_to_roman(int a)
{
    string ans;
    string M[] = {"","M","MM","MMM"};
    string C[] = {"","C","CC","CCC","CD","D","DC","DCC","DCCC","CM"};
    string X[] = {"","X","XX","XXX","XL","L","LX","LXX","LXXX","XC"};
    string I[] = {"","I","II","III","IV","V","VI","VII","VIII","IX"};
    ans = M[a/1000]+C[(a%1000)/100]+X[(a%100)/10]+I[(a%10)];
    return ans;
}
Neha Agarwal
  • 51
  • 1
  • 2
4

One major problem is here:

if(input = 100)

I think you mean

if(input == 100)

You would have found this very easy if you stepped through your code in a debugger. Remember that a debugger is a programmers best friend, and the first tool to use if things doesn't work as intended.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • 1
    My debugger didn't catch that actually – Jim Slatten Oct 09 '13 at 08:06
  • 2
    @JimSlatten even better than a debugger would be to turn on all warnings in your compiler, this would show up at compile time thus no need to debug. – Motti Oct 09 '13 at 08:08
  • 1
    @JimSlatten It might not "catch" that, but if you step through the code line by line then you would have seen `input` changing value *and* entering the code block even if `input` wasn't `100` before. – Some programmer dude Oct 09 '13 at 08:08
  • 1
    @JoachimPileborg: Learning to use a debugger is an acquired skill, and experienced developers aren't even aware anymore that they have that skill. We have a mental model of what the variables should be, which branches should be taken, and compare that to what the debugger shows. – MSalters Oct 09 '13 at 11:11
1

I think this can actually be solved much more simply than your attempt, where frankly I fail to understand what you are trying to do (but that's me).

Anyway, it can just be a sequence of if/else, not even nested. All you need to do is to check what is the "largest" literal contained in the input number, note it and then subtract the value if represents from the input number. Continue in such a way until you get to 0.

e.g. (I'm not sure this is C++ syntax, but you can adjust it of course):

string roman = ""
if(input == 100)
{
    roman += "C";
    input -= 100;
}

if(input >= 50)
{
    roman += "L";
    input -= 50;
}

And so on, you can figure the rest out on your own (it's your test after all).

Two things:

  • some literals can be repeated (3: III, 20: XX).
  • writing e.g. "XXXX" for 40 instead of "XL" is still a valid roman number (although less common), so if I were evaluating your test I would accept it, but that depends on the assignment. (http://en.wikipedia.org/wiki/Roman_numerals)
elnigno
  • 1,751
  • 14
  • 37
0

Joachim found the first problem, this code is always executed and overwrite input with 100.

    if(input = 100)
    {
        romnum + 'C';

    }

Now, why don't you see anything? That's because you miss another =. All other code correctly uses += but this uses +. As a result, this doesn't assign the resulting string back to romnum.

BTW, since romnum is still empty, you can use romnum = 'C' or romnum += 'C' interchangeably.

MSalters
  • 173,980
  • 10
  • 155
  • 350
0

I wrote this for fun; maybe useful. Note however, that it will not work for values greater than 1000. Can adapt it to suit your needs though. Here you go:

enum roman_digits{
    I=1,
    V=5,
    X=10,
    L=50,
    C=100,
    D=500,
    M=1000
};

std::string lookup(roman_digits v) {
    switch (v) {
    case I:
        return "I";
    case V:
        return "V";
    case X:
        return "X";
    case L:
        return "L";
    case C:
        return "C";
    case D:
        return "D";
    case M:
        return "M";
    default:
        return NULL;
    }
}

std::string to_roman(const int value) {
    roman_digits weight[] = { I, V, X, L, C, D, M };
    std::string result;
    int t;
    int i;

    if (value == 0) {
        return NULL;
    } else {
        unsigned int i;
        for (i = 0; i < sizeof(weight) / sizeof(roman_digits); ++i) {
            if (value == weight[i]) {
                return lookup(weight[i]);
            }
        }
    }
    i = 0;
    t = value;
    while (t > 0) {
        t = value;
        t /= weight[i++];
    }
    --i;
    int prev_wt_sub = i % 2 ? (i - 1) : (i - 2);
    if ((weight[i] - weight[prev_wt_sub]) < value) {
        result += lookup(weight[prev_wt_sub]) + lookup(weight[i]) +
                to_roman(value - (weight[i] - weight[prev_wt_sub]));
    } else if ((weight[i] - weight[prev_wt_sub]) > value) {
        prev_wt_sub += (value / weight[prev_wt_sub + 1] ? 1 : 0);
        result += lookup(weight[prev_wt_sub]) +
                to_roman(value - weight[prev_wt_sub]);
    } else {
        result += lookup(weight[prev_wt_sub]) + lookup(weight[i]);
    }

    return result;
}
user2338150
  • 479
  • 5
  • 14
0

//java code

import java.io.*;

public class NumberToRoman {

public static void main(String[] args) throws IOException{


    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    System.out.println("Enter any number");
    int  num= Integer.parseInt(br.readLine());

     NumberToRoman n = new  NumberToRoman();
     n.conversion(num);

    }




public void conversion(int y) {
    int i=0;

    int decimal[] = {1000,900,500,400,100,90,50,10,9,5,4,1};
    String roman[]= {"M","CM","D","CD","C","XC","L","X","IX","V","IV","I"};
    while(y!=0) {
          while(y/decimal[i]!=0) {
              System.out.print(roman[i]);
              y=y-decimal[i];


          }
          i++;

    }


}

}

Thrishool MSM
  • 337
  • 3
  • 11
0

Function to Convert Decimal to Roman Numrals string toLongRoman(int x) {

string Romanvalue;

string  Roman[13] = { "M","CM","D","CD", "C","XC", "L","XL", "X","IX","V","IV", "I" };
int Numbers[13] = { 1000, 900, 500,400, 100,90,50,40,10,9,5,4,1 };

for (int index = 0; index < 13; index++) {



        while (x >= Numbers[index]) {
            Romanvalue += Roman[index];


            x -= Numbers[index];

        }
    }

    return Romanvalue;
0

Here's my solution. A bit brute force-ish and could be refactored but actually runs pretty fast and was easy to debug (ran perfectly first try). It does have nested ifs so that you never check the 100s, 1000s etc if there are no 10s.

   string intToRoman(int num) {
            string retVal="";
            int ones=num%10;
            cout<<ones<<endl;
            int onesRest=(num-ones)/10;
                switch (ones){
                    case 1:
                        retVal="I";
                        break;
                    case 2:
                        retVal="II";
                        break;
                    case 3:
                        retVal="III";    
                        break;
                    case 4:
                        retVal="IV";
                        break;
                    case 5:
                        retVal="V";    
                        break;
                    case 6:
                        retVal="VI";
                        break;
                    case 7:
                        retVal="VII";    
                        break;
                    case 8:
                        retVal="VIII";
                        break;
                    case 9:
                        retVal="IX";
                        break;
                }

            if(onesRest>0){
                int tens=onesRest%10;
                int tensRest=(onesRest-tens)/10;            
                switch (tens){
                    case 1:
                        retVal="X"+retVal;
                        break;
                    case 2:
                        retVal="XX"+retVal;
                        break;
                    case 3:
                        retVal="XXX"+retVal;   
                        break;
                    case 4:
                        retVal="XL"+retVal;
                        break;
                    case 5:
                        retVal="L"+retVal;   
                        break;
                    case 6:
                        retVal="LX"+retVal;
                        break;
                    case 7:
                        retVal="LXX"+retVal;  
                        break;
                    case 8:
                        retVal="LXXX"+retVal;
                        break;
                    case 9:
                        retVal="XC"+retVal;
                        break;

            }
            if(tensRest>0){
                int hundreds=tensRest%10;
                int hundredsRest=(tensRest-hundreds)/10;            
                switch (hundreds){
                    case 1:
                        retVal="C"+retVal;
                        break;
                    case 2:
                        retVal="CC"+retVal;
                        break;
                    case 3:
                        retVal="CCC"+retVal;   
                        break;
                    case 4:
                        retVal="CD"+retVal;   
                        break;
                    case 5:
                        retVal="D"+retVal;      
                        break;            
                    case 6:
                        retVal="DC"+retVal;   
                        break;
                    case 7:
                        retVal="DCC"+retVal;       
                        break;
                    case 8:
                        retVal="DCCC"+retVal;   
                        break;
                    case 9:
                        retVal="CM"+retVal;      
                        break;
                }
                if(hundredsRest>0){
                    int thousands=hundredsRest%10;           
                    switch (thousands){
                        case 1:
                            retVal="M"+retVal;   
                            break;
                        case 2:
                            retVal="MM"+retVal;   
                            break;
                        case 3:
                            retVal="MMM"+retVal;     
                            break;    
                    }

                }  
            }    
        }
            return retVal;
        }
Rik
  • 1,870
  • 3
  • 22
  • 35