Link to home
Start Free TrialLog in
Avatar of any
any

asked on

C++ help with roman numerals

this is my second question, because no one answers the first one.
I need to make a programm, where you enter a roman numeral, then another one, then arithmetic sign and the programm should caculate the answer and give the answere in Roman numerals and in normal. I am trying to do it using substings, but I am really bad at it.
Please help me with my programm. Please.
Thanks.

This is what I have:

#include<iostream>
#include<string>

using namespace std;
int Function(int);
int main()
{
    string Roman;
     int counter;
     string Roman1;
    int I = 1, V= 5, X= 10, L= 50, C=100, D=500, M=1000;
    char Operation;

    cout<<"Enter the number"<<endl;
    cin>>Roman;
    cout<<"Enter the second one"<<endl;
    cin>>Roman1;
    cout<<"Enter the operation"<<endl;
    cin>>Operation;


    if (Operation = '-')
    {
    cout<<Function(counter) - Function (counter);
    }
    else if (Operation = '+')
    {
    cout<<Function(counter) - Function (counter);
    }
    else if (Operation = '/')
    {
    cout<<Function(counter) / Function (counter);
    }
    else if (Operation = '*')
    {
    cout<<Function(counter) * Function (counter);
    }
   
    return 0;

}
int Function(int counter)
{
     int newt;
    string Roman;
    counter = 0;
    int I = 1, V= 5, X= 10, L= 50, C=100, D=500, M=1000;
    while(Roman.substr(newt, 1) != '\n')
    {
        if(Roman.substr(newt, 1) == 'I')
        {
            counter = counter + 1;
        }
        else if (Roman.substr(newt, 1) == 'V')
        {
            counter = counter  + 5;
        }
        else if (Roman.substr(newt, 1) == 'X')
        {
            counter = counter + 10;
        }
        else if (Roman.substr(newt, 1) == 'L')
        {
            counter = counter + 50;
        }
        else if (Roman.substr(newt, 1) == 'C')
        {
            counter = counter + 100;
        }
        else if (Roman.substr(newt, 1) == 'D')
        {
            counter = counter + 500;
        }
        else if (Roman.substr(newt, 1) == 'M')
        {
            counter = counter + 1000;
        }
        newt++;
    }
        return counter;
}

Avatar of nietod
nietod

For safety sake the line

   int I = 1, V= 5, X= 10, L= 50, C=100, D=500, M=1000;

should be

   const int I = 1, V= 5, X= 10, L= 50, C=100, D=500, M=1000;

this insures that none of these value ever get changed by mistake, which woudl definitely cause the program to missbehave.

calling a fucntion "function" like in
   int Function(int counter)
is a bad practice.  All functions are functions.   What if we start calling all people "person"  Can you imagine the confussion.  you call a place and ask to speak to "person".   No not that "person" the other "person".  No, not that one either, I mean the one named "person".  

If this function is meant to convert roman numbers to integers, then call it that.   Like RomanToInteger().


All the code like

  if (Operation = '-')
   {
       cout<<Function(counter) - Function (counter);

is wrong.   Why is "counter" being pased to "function"   I have no idea why you even need "counter" but it is not a roman number.  it is an uninitialized integer, that is, it is set to a random number.   its not very useful at the moment.

If you are using strings to represent romans numbers and if Function is meant to convert roman numbers to integers, then don't you think you should pass a string to Function()?


inside function() newt is never intialized.  It starts out as a random number.

function() "operatores" on a string that is local to it, not passed to it, and this string is always empty.  (0 characters long).   You search the string for a "\n" character.  Its not there.  Nothing is there.


Note that when you do

cin>>Roman;

You don't get a \n at the end of the string.  You can use Roman.length() to get the string's length, but you can't search for a \n, its not there.


That should get you started.    Work on that and post what you get done.

Avatar of any

ASKER

Can you expalin again what I should do with the if (Operation = '-')
  {
      cout<<Function(counter) - Function (counter);


You said: function() "operatores" on a string that is local to it, not passed to it, and this string is always empty.  (0 characters long).   You search the string for a "\n" character.  Its not there.  Nothing is there.

what should I do with it?

This is what I have now:


#include<iostream>
#include<string>

using namespace std;
int RomanToInt(int);
int main()
{
    string Roman;
     int counter;
     string Roman1;
    const int I = 1, V= 5, X= 10, L= 50, C=100, D=500, M=1000;
    char Operation;

    cout<<"Enter the number"<<endl;
    cin>>Roman;
    cout<<"Enter the second one"<<endl;
    cin>>Roman1;
    cout<<"Enter the operation"<<endl;
    cin>>Operation;


    if (Operation = '-')
    {
    cout<<RomanToInt(counter) - RomanToInt (counter);
    }
    else if (Operation = '+')
    {
    cout<<RomanToInt(counter) - RomanToInt (counter);
    }
    else if (Operation = '/')
    {
    cout<<RomanToInt(counter) / RomanToInt (counter);
    }
    else if (Operation = '*')
    {
    cout<<RomanToInt(counter) * RomanToInt (counter);
    }
   
    return 0;

}
int RomanToInt(int counter)
{
     int newt =0;
    string Roman;
    counter = 0;
    int I = 1, V= 5, X= 10, L= 50, C=100, D=500, M=1000;
    while(Roman.length() <= Roman)
    {
        if(Roman.substr(newt, 1) == 'I')
        {
            counter = counter + 1;
        }
        else if (Roman.substr(newt, 1) == 'V')
        {
            counter = counter  + 5;
        }
        else if (Roman.substr(newt, 1) == 'X')
        {
            counter = counter + 10;
        }
        else if (Roman.substr(newt, 1) == 'L')
        {
            counter = counter + 50;
        }
        else if (Roman.substr(newt, 1) == 'C')
        {
            counter = counter + 100;
        }
        else if (Roman.substr(newt, 1) == 'D')
        {
            counter = counter + 500;
        }
        else if (Roman.substr(newt, 1) == 'M')
        {
            counter = counter + 1000;
        }
        newt++;
    }
        return counter;
}



Please help more!!
thanks



>> Can you expalin again what I should do with the if (Operation = '-')
>>    {
>>  cout<<Function(counter) - Function (counter);

This says.   Runs something called "Function" on a random number, which then doesn't use that random number in any way.   Then do that a 2nd time and calculate the difference (subtract).    That doesn't seem usefull

Don't you want to work with the numbers the user entered?
Don't you think your Function() should operate on roman numbers, not an int?  (I'm not 100% sure because I can't be sure what you want to do with it, since it is called "function")

Now you have


cout<<RomanToInt(counter) - RomanToInt (counter);

but "counter" isn't  a romman number    its an integer.  its set to a random value too.

RimanToInt() still tries to convert he value stored in "roman" (declared in RomanToInt, not in main) to an integer.  Thsi strign is empty.  There is no roman number in it.   there might be roman numbers in the strings declared in main.
Avatar of any

ASKER

so can you please show me what I should do, because I am very bad at it. Should I have >>  cout<<Function(Roman) - Function (Roman1);And if so, how should I make the function work?The function is only for Roman, not for Roman1!!!

Avatar of any

ASKER

I really need help on this programm. If someone could just tell me how to do it, I would understand what I am missing. Please help me with this programm. I am really confused with functions with everything else conserning this program! And also can someone tell me what this error means and what should I do:

binary '==' : 'class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >' does not define this operator or a conversion to a t
ype acceptable to the predefined operator

Thanks!
Here is the correct Code,for Explanation look at your first
Question on this topic...

#include<iostream>
#include<string>

using namespace std;
int Function(string);
int main()
{

    string Roman1,Roman2;

    char Operation;
while(Operation!='q')
{
    cout<<"Enter the number"<<endl;
    cin>>Roman1;
    cout<<"Enter the second one"<<endl;
    cin>>Roman2;
    cout<<"Enter the operation"<<endl;
    cin>>Operation;


    if (Operation == '-')
    {
    cout<<Function(Roman1) - Function (Roman2);
    }
    else if (Operation == '+')
    {
    cout<<Function(Roman1) + Function (Roman2);
    }
    else if (Operation == '/')
    {
    cout<<Function(Roman1) / Function (Roman2);
    }
    else if (Operation == '*')
    {
    cout<<Function(Roman1) * Function (Roman2);
    }

}
    return 0;

}
//----------------------------------------------------------
int Function(string Roman)
{

    int counter = 0,temp;
    bool isI=0;

    for(unsigned int now=0;now <= Roman.length();now++)
    {    string rom=Roman.substr(now,1);
         if(rom == "I")
         {  if(isI)counter +=1;
            else isI=1;
            if(Roman.length()==now+1)counter=1;
         }
         else if (rom== "V")
         {  if(isI)
                    {counter--;
                    isI=0;
                    }
              counter +=5;
         }
         else if (rom== "X")
         {    if(isI)
                    {counter--;
                    isI=0;
                    }
              counter +=10;
         }
         else if (rom == "L")
         {    if(isI)
                    {counter--;
                    isI=0;
                    }
              counter +=50;
         }
         else if (rom == "C")
         {    if(isI)
                    {counter--;
                    isI=0;
                    }
              counter +=100;
         }
         else if (rom == "D")
         {    if(isI)
                    {counter--;
                    isI=0;
                    }
              counter +=500;
         }
         else if (rom == "M")
         {    if(isI)
                    {counter--;
                    isI=0;
                    }
              counter +=1000;
         }

    }
         return counter;
}


Made a mistake in function,it didn't work correct yet
(With VI for example).
Now this should really do it:

int Function(string Roman)
{

    int counter = 0,temp;
    bool isI=0;

    for(unsigned int now=0;now <= Roman.length();now++)
    {    string rom=Roman.substr(now,1);
         if(rom == "I")
         {  counter++;
            isI=1;

         }
         else if (rom== "V")
         {    if(isI)
                 counter-=2;

              counter+=5;
         }
         else if (rom== "X")
         {    if(isI)
                 counter-=2;

              counter +=10;
         }
         else if (rom == "L")
         {    if(isI)
                 counter-=2;

              counter +=50;
         }
         else if (rom == "C")
         {    if(isI)
                 counter-=2;

              counter +=100;
         }
         else if (rom == "D")
         {    if(isI)
                 counter-=2;

              counter +=500;
         }
         else if (rom == "M")
         {    if(isI)
                 counter-=2;

              counter +=1000;
         }

    }
         return counter;
}
Here is some code that works, complete with error checking and user friendly messages. I could have made it a little more efficient, but at the cost of complexity.

// Build using    g++ roman.cpp -o roman

#include <string>

/********************************************************************
 * convert - convert roman value to int value, return
 *           true if successful
 ********************************************************************/
bool convert( string& roman, int& value )
{
   bool rtn = true;
   int v = 0;
   
   for ( int i=0; rtn && ( i < roman.length() ); i++ )
   {
      switch ( roman[i] )
      {
         case 'i':
         case 'I':
            v += 1;
            break;
         case 'v':
         case 'V':
            v += 5;
            break;
         case 'x':
         case 'X':
            v += 10;
            break;
         case 'l':
         case 'L':
            v += 50;
            break;
         case 'c':
         case 'C':
            v += 100;
            break;
         case 'd':
         case 'D':
            v += 500;
            break;
         case 'm':
         case 'M':
            v += 1000;
            break;
         default:
            rtn = false;
            break;
      }
   }
   
   // Only update value if we did not encounter an error
   if ( rtn )
      value = v;
   else
      cout << "Error. Try again." << endl;
   
   return rtn;
}

/********************************************************************
 * main
 ********************************************************************/
int main( int argc, char* argv[] )
{
   string roman1, roman2, operation;
   int value1, value2;
   bool err;

   do
   {
      cout << "Enter the first number (IVXLCDM): " << endl;
      cin  >> roman1;
      err = !convert( roman1, value1 );
   }
   while ( err );

   do
   {
      cout << "Enter the second number (IVXLCDM): " << endl;
      cin  >> roman2;
      err = !convert( roman2, value2 );
   }
   while ( err );
   
   do
   {
      err = false;
      float result;
     
      cout << "Enter the operation: " << endl;
      cin  >> operation;
     
      switch ( operation[0] )
      {
         case '+':
            cout << "Adding: " << value1 << " + " << value2 << endl;
            result = value1 + value2;
            break;
         case '-':
            cout << "Subtracting: " << value1 << " - " << value2 << endl;
            result = value1 - value2;
            break;
         case '/':
            cout << "Dividing: " << value1 << " / " << value2 << endl;
            if ( value2 )
               result = ( float ) value1 / value2;
            else
               err = true;
            break;
         case '*':
            cout << "Multiplying: " << value1 << " * " << value2 << endl;
            result = value1 * value2;
            break;
         default:
            err = true;
            break;
      }
      if ( !err )
         cout << "The result is " << result << endl;
      else
         cout << "Error. Try again." << endl;
   }
   while ( err );
     

   return 0;
}
Also, there is another thing with Roman numerals, in that you need to determine subtraction in some cases. For example 'VII' means 7 (5 + 1 + 1) but 'IV' means 4 (5 - 1).
I forgot about that when doing my code sample above. Sorry. But from the looks of it, so did most everyone else, except sdyx.
This one is a little better using a map. It now checks for all 'subtract' cases, which in previous code only the '1' is checked, but that is not always the case.
http://www.novaroma.org/via_romana/numbers.html

I still do not check for run on values like VIIIIIII, which is illegal. If the input roman numeral is valid, this should work, however.

==============================
// Build using    g++ roman.cpp -o roman

#include <string>
#include <map>


typedef map< char, int > RMN2INT_T;
RMN2INT_T rmn2int;

/********************************************************************
 * convert - convert roman value to int value, return
 *           true if successful
 ********************************************************************/
bool convert( string& roman, int& value )
{
   bool rtn = true;
   int v = 0, temp1, temp2;
   
   for ( int i=0; rtn && ( i < roman.length() ); i++ )
   {
      // First see of the character is a valid roman numeral
      temp1 = rmn2int[ roman[ i ] ];
      if ( temp1 )
      {  
         // Check to see if the next character is 'larger' than
         // this value (skip this if we are on the last character)
         if ( i < roman.length() - 1 )
            temp2 = rmn2int[ roman[ i + 1 ] ];
         else
            temp2 = 0;
           
         // If the next character is larger (IV, IX), then subtract temp1 from running total.
         // If the next character is smaller (VI, XI), then add temp1 from running total.
         if ( temp2 <= temp1 )
            v += temp1;
         else
            v -= temp1;
      }
      else
         rtn = false;
   }
   
   // Only update value if we did not encounter an error
   if ( rtn )
   {
      cout << "Roman numeral " << roman << " converted to " << v << " successfully" << endl;
      value = v;
   }
   else
      cout << "Error. Try again." << endl;
   
   return rtn;
}

/********************************************************************
 * main
 ********************************************************************/
int main( int argc, char* argv[] )
{
   string roman1, roman2, operation;
   int value1, value2;
   bool err;

   rmn2int[ 'I' ] = 1;
   rmn2int[ 'V' ] = 5;
   rmn2int[ 'X' ] = 10;
   rmn2int[ 'L' ] = 50;
   rmn2int[ 'C' ] = 100;
   rmn2int[ 'D' ] = 500;
   rmn2int[ 'M' ] = 1000;
   rmn2int[ 'i' ] = 1;
   rmn2int[ 'v' ] = 5;
   rmn2int[ 'x' ] = 10;
   rmn2int[ 'l' ] = 50;
   rmn2int[ 'c' ] = 100;
   rmn2int[ 'd' ] = 500;
   rmn2int[ 'm' ] = 1000;
   
   do
   {
      cout << endl << "Enter the first number (IVXLCDM): " << endl;
      cin  >> roman1;
      err = !convert( roman1, value1 );
   }
   while ( err );

   do
   {
      cout << endl << "Enter the second number (IVXLCDM): " << endl;
      cin  >> roman2;
      err = !convert( roman2, value2 );
   }
   while ( err );
   
   do
   {
      err = false;
      float result;
     
      cout << endl << "Enter the operation: " << endl;
      cin  >> operation;
     
      switch ( operation[0] )
      {
         case '+':
            cout << "Adding: " << value1 << " + " << value2 << endl;
            result = value1 + value2;
            break;
         case '-':
            cout << "Subtracting: " << value1 << " - " << value2 << endl;
            result = value1 - value2;
            break;
         case '/':
            cout << "Dividing: " << value1 << " / " << value2 << endl;
            if ( value2 )
               result = ( float ) value1 / value2;
            else
               err = true;
            break;
         case '*':
            cout << "Multiplying: " << value1 << " * " << value2 << endl;
            result = value1 * value2;
            break;
         default:
            err = true;
            break;
      }
      if ( !err )
         cout << "The result is " << result << endl;
      else
         cout << "Error. Try again." << endl;
   }
   while ( err );
     

   return 0;
}

Here's another short function from
https://www.experts-exchange.com/questions/20421971/Roman-Numeral-Converter.html
Also doesn't work with illegal romans...


#include <map.h>
#include <string.h>

int toDec(string roman)
{
    int val=0;
    map<char, int> valMap;
    valMap['I']=1;
    valMap['V']=5;
    valMap['X']=10;
    valMap['L']=50;
    valMap['C']=100;
    valMap['D']=500;
    valMap['M']=1000;

    string::iterator i=roman.begin();
    while( i!=roman.end() )
    {
         int t=0;
         string::iterator old=i;
         for(; *i==*old && i!=roman.end(); i++ ) t+=valMap[*i];
         if( valMap[ *i ] > valMap[ *old ] && i!=roman.end() ) val -= t;
         else val +=  t;
    }
    return val;
}
Now this should do it,i've modified my function so that
in case of an illegal number 0 is returned:

int Function(string Roman)
{

   int counter = 0,temp,isLegal=0;
   bool isI=0,legalM=0,legalC=0,legalD=0,legalX=0,legalL=0,legalV=0,legalI=0;
/*those are used to see if a sign is still allowed*/
   for(unsigned int now=0;now <= Roman.length();now++)
   {    string rom=Roman.substr(now,1);
        if(rom == "I")
        {  counter++;
           isI=1;
           isLegal++;
           if(legalI)return 0;
        }
        else if (rom== "V")
        {    if(legalV)return 0;
             if(isI){
                counter-=2;
                legalI=true;
                legalV=true;}
             legalM=true;
             legalD=true;
             legalC=true;
             legalL=true;
             legalX=true;

             counter+=5;
        }
        else if (rom== "X")
        {    if(legalX) return 0;
             if(isI){
                counter-=2;
                legalI=true;
                legalX=true;}
             legalM=true;
             legalD=true;
             legalC=true;
             legalL=true;

             counter +=10;
        }
        else if (rom == "L")
        {    if(legalL)return 0;
             if(isI){
                counter-=2;
                legalI=true;
                legalL=true;}
             legalM=true;
             legalD=true;
             legalC=true;
             counter +=50;
        }
        else if (rom == "C")
        {    if(legalC)return 0;
             if(isI){
                counter-=2;
                legalI=true;
                legalC=true;}
             legalM=true;
             legalD=true;
             counter +=100;
        }
        else if (rom == "D")
        {    if(legalD)return 0;
             if(isI){
                counter-=2;
                legalI=true;
                legalD=true;}
             legalM=true;
             counter +=500;
        }
        else if (rom == "M")
        {    if(legalM)return 0;
             if(isI){
                counter-=2;
                legalI=true;
                legalM=true;}
             counter +=1000;
        }

   }
   if(isLegal>3 )return 0;
        return counter;
}
EXPERTS  PLEASE THINK HERE!!!!!

THIS IS NOT THE SOURCE CODE TO A NEW MATH PACKAGE.  NO ONE DOES MATH IN ROMAN NUMERALS FOR A GOOD REASON.   THIS IS A HOMEWORK ASSIGNMENT.    YOU CAN PROVIDE HELP, BUT DON'T GIVE THE ANSWER.

Any, I'm afraid much of the "asnwers" provided is wrong anyways.   For example, they don;t take into account the order of the symbols in the roman number.   That is very important.   IV is not the same as VI but the code shown will convert them the same.
Here is my program that will correctly decode any roman numeral to base 10.


#include <iostream>
#include <string>

using namespace std;

//A quick and easy function to determine the value of a letter.
//Also keeps track of last three numbers evaluated for error checking in global int array.
int eval( char &, int );
int last3nums[3] = {0, 0, 0};

//Determine the value of a number in roman numeral form.
int roman2int( char * );

int main()
{
     char Roman1[256];

     cout << endl << "Please enter a valid number using roman numerals:";
     cin.getline( Roman1, 255);

     cout << endl << endl << roman2int( Roman1 ) << endl;

     return 0;
}

//Evaluation function with optional error checking (default: error checking ON).
int eval( char &letter, int error_check = 1 )
{
     int value;
     int digits;

     if( letter == 'i' || letter == 'I' ){
          digits = 1;
          value =     1;
     }
     else if( letter == 'v' || letter == 'V' ){
          digits = 1;    
          value = 5;
     }
     else if( letter == 'x' || letter == 'X' ){
          digits = 2;    
          value = 10;
     }
     else if( letter == 'l' || letter == 'L' ){
          digits = 2;
          value = 50;
     }
     else if( letter == 'c' || letter == 'C' ){
          digits = 3;
          value = 100;
     }
     else if( letter == 'd' || letter == 'D' ){
          digits = 3;
          value = 500;
     }
     else if( letter == 'm' || letter == 'M' ){
          digits = 4;
          value = 1000;
     }
     else{
          if( error_check == 1 )
          {
               cout << endl << "\"" << letter << "\" is an INVALID roman numeral." << endl;
               exit( -1 );
          }
          else return -1;
     }
     last3nums[2] = last3nums[1];
     last3nums[1] = last3nums[0];
     last3nums[0] = digits;
     return value;
}

int roman2int( char *roman )
{
     int length = (int)strlen( roman );

     if( length == 1 ) return eval(roman[0]);

     int chars_processed = 0; //temporary counter for string parsing.
     int total = 0; //tally variable
     char *temp;

     while( length > chars_processed )
     {
          temp = &roman[chars_processed];
          //The case of a lesser number following a greater number
          if( eval(temp[0]) < eval(temp[1], 0) )
          {
               //Error checking for when the lower roman numeral is found before a larger one.
               //Example: IX and IV are valid numbers.  IL and VM are not.
               if( (last3nums[0]-last3nums[1] == 0) || (last3nums[0]-last3nums[1] == 1) )
               {
                    total += ( eval(temp[1])-eval(temp[0]) );
                    chars_processed += 2;
               }
               else
               {
                    cout << endl << "\"" << temp[0] << temp[1] << "\" is an INVALID roman numeral." << endl;
                    exit( -2 );
               }
          }
          else
          {
               if( length - chars_processed == 2 )
               {
                    for( int x=0; x<2; ++x)
                    {
                         total += eval(temp[x]);
                         ++chars_processed;
                    }
               }
               else
               {
                    total += eval(temp[0]);
                    ++chars_processed;
               }
          }
     }
     return total;
}

SssupperDo0d, this is a homework assigment.   You can be removed from experts exchange for posting something like this!   You can HELP student.  You can't help them to cheat--even if they don't wnat to cheat!

fortunately that code isn't right either!
Ok, I could understand the cheating remark.  Sorry people, I just started browsing this site yesterday.

But, how is it not correct? What did I forget?
Ok, I could understand the cheating remark.  Sorry people, I just started browsing this site yesterday.

But, how is it not correct? What did I forget?
Ok, I could understand the cheating remark.  Sorry people, I just started browsing this site yesterday.

But, how is it not correct? What did I forget?
Ok, I could understand the cheating remark.  Sorry people, I just started browsing this site yesterday.

But, how is it not correct? What did I forget?
Nevermind, I believe I found it.  By my algorithm it's just a matter of keeping track of the last number added, and ensuring that it is either less or equal to the last added number.  Was there something else as well?
>> By my algorithm it's just a matter of keeping track of the last number
>> added, and ensuring that it is either less or equal to the last added
>> number.
that is one key peice to doing the conversion right.   Ther are others.  Its a little hard to tell what is right or wrong in that code, though.  You might think about 49 though.
Avatar of any

ASKER

I will not cheat and copy the code that SssupperDoOd gave me. I am just trying to get some help and I made this so far and it worked, untill I added the function last function that converts number back to Roman numeral. Please give me some help with that. Thanks.

here is my programm:#include<iostream>
#include<string>

using namespace std;
int RomanToInt(string);
int IntToRoman(int);
int main()
{

     string Roman1;
     string Roman2;
     int Roman3;
     char Operation;
     char Q;

while(Q!='q')
{
   cout<<"Enter the Roman numeral: ";
   cin>>Roman1;
   cout<<"Enter the second Roman numeral: ";
   cin>>Roman2;
   cout<<"Enter the arithmetic operation: ";
   cin>>Operation;
     
   cout<<endl<<endl;

   if (Operation == '-')
   {
     Roman3= RomanToInt(Roman1) - RomanToInt (Roman2);
     cout<<Roman3<<endl;
     IntToRoman(Roman3);
   }
   else if (Operation == '+')
   {
     Roman3= RomanToInt(Roman1) - RomanToInt (Roman2);
   cout<<Roman3<<endl;
     IntToRoman(Roman3);
   }
   else if (Operation == '/')
   {
     Roman3= RomanToInt(Roman1) - RomanToInt (Roman2);
   cout<<Roman3<<endl;
     IntToRoman(Roman3);
   }
   else if (Operation == '*')
   {
     Roman3= RomanToInt(Roman1) - RomanToInt (Roman2);
   cout<<Roman3<<endl;
     IntToRoman(Roman3);
   }
     cout<<"Please press any key go again, otherwise enter: 'q'"<<endl;
     cin>>Q;
}
   return 0;

}

int RomanToInt(string Roman)
{

   int counter = 0;
   int now=0;

     while(now <= Roman.length())  
     {    
          string rom=Roman.substr(now,1);
        if(rom == "I")
        {  counter++;

        }
        else if (rom== "V")
        {  

             counter+=5;
        }
        else if (rom== "X")
        {  

             counter +=10;
        }
        else if (rom == "L")
        {  
             counter +=50;
        }
        else if (rom == "C")
        {    

             counter +=100;
        }
        else if (rom == "D")
        {    

             counter +=500;
        }
        else if (rom == "M")
        {    

             counter +=1000;
        }
               now++;
   }

         
        return counter;
}

int IntToRoman(int num)
{
     string written = " ";
     
     while(num>=1000)
     {
     if(num/1000>=1)
     {
          written = written + "M";
          num-=1000;
     }
     }
     while(num>=500)
     {
     if(num/500)
     {
          written = written + "D";
          num-=500;
     }
     }
     while(num>=100)
     {
     if(num/100>1)
     {
          written = written + "C";
               num-=100;
     }
     }
     while(num>50)
     {
     if(num/50>1)
     {
          written = written + "L";
          num-=50;
     }
     }
     while(num>10)
     {
     if(num/10>1)
     {
          written = written + "X";
          num-=50;
     }
     }
     while(num>5)
     {
          if(num/5>1)
          {
               written = written + "V";
               num-= 5;
          }
     }
     while(num>1)
     {
     if(num/1)
     {
          written = written + "I";
               num-=1;
     }
     }
     cout<<written<<endl;
     return 0;
}

Avatar of any

ASKER

it only does subtruction
Avatar of any

ASKER

for everything
>> I will not cheat and copy the code that SssupperDoOd gave
>> me. I am just trying to get some help
Good for you!


Unfortunately, I don't have much time now.   But I'll do my best for the moment.    Hopwfully you have a few days before this is due.   (This is a very tricky assignment.)

when i see

   int RomanToInt(string);
   int IntToRoman(int);

I can guess there is a problem.   RomanToInt() takes a string.   That makes sense you are using strings to store the roman numbers.    But InttoRoman() returns a roman number.  so it has to return data type?

Here you are just confussing yourself and any other reader
   string Roman1;
   string Roman2;
   int Roman3;
Later on in the code someone will see Roman1 and assume--rightly--that it is a roman number.  Same with Roman2.  but Roman3--surprise--isn't.  its an integer.    You will just misslead yourself this way.    Names are menat to make things clear, not confussing.     Call it ResultInt or something like that.


>> Roman3= RomanToInt(Roman1) - RomanToInt (Roman2);
>> cout<<Roman3<<endl;
>> IntToRoman(Roman3);

This is close.   You take the roman numbers and convert them to integer to do the math.  good.  But when you need to print the result you need to print it in roman numbes.   i.e. you need to convert the integer result to roman numbers.  You've made it look like you've done that because the result is called "Roman3"  but that is missleading.  its still an integer.   This occurs again and again.

continues
Now lets talk about how roman numbers are "constructed"

Usually the "digits"  occur from most significant (largest) to least significant (smallest)  i.e.. l;ike   MCLXVI

If they occur in this order only, then your code for rommantoint should work.   unfortunately, that is not the only case.  any time least significant digits occur before more significant digits, then their value is not added onto the result, but subtracted.  i.e. in

XXIV

the I comes before the V, they are out of order, so in that case the I (1) is subtracted, not added.

To convert any roman number (including some invalid ones, like VX) you have to start processing from the left and add up all the digits of the same type (letter) until you come to a new digit (letter).    Then if the next digit is of lower signficance, you add the value oft the digits you just collected to the reult.  If the value of the next digit is higher in significance, you subtract the value of the digits you collected from the result.  

continues
Avatar of any

ASKER

I don't need subtruction, I doing very easy just additioin, so IV would be 6.
Avatar of any

ASKER

And the code doesn't work
For example

LXXIV

you start with a "result" of 0.

First you get the first L.  It has a value fo 50.  then you get the next letter and it is an X.  This is not an L, so now you need to decide what to do with the digits (oone digit really) you collected.  Since L is more significant (larger) than X, you add the collected value (50) to the result.   Result is now 50.

Now you "collect" the Xs.  There are 2, that is 20.   Then you come to an I.   since I is less signficiant than X, you add the collected value to the result.  50+20 = 70.  result is 70.

Now you collect the Is.  There is 1.  That is 1.   now the next digit is a V.  That is more significant than an I.  In this case you subtract the collected value (1) from the result.   Result is 70 - 1 = 69.

Now you collect the Vs.  There is only 1.  There is no next digit, so in this case the V has to be more significant than the next digit (0).   so wee add the collected vlaue (5) to the result.   Result is 69+5 = 74.

Fun huh?

Try that   (Don't even think about int to roman yet!)
Well I agree with nietod that we should not be providing the solutions, since these are typically homework assignments, and providing the answer does not help the student for the long term.

I am still a little baffled why we are still talking about the subtract case when I addressed it several posts ago, and yes, that code I posted works perfectly with all subtract cases, even the stuff mentioned in the immediately previous post. I had tested several numbers and they all worked.

I mentioned another snag the student should watch for, where you could have too many roman numerals as an input, for example, VIIIIII is invalid. You can never have more than three 'I's in a row. I think, however, that the student does not care for this much detail, since they did not care about the subtract issue!

As for the conversion back to roman of the result, I would try a simple plan. Start with the resultant 'int' number and a blank string. Then, if the number is greater than 1000, subtract 1000 from the number, and add an "M" to the string. Rinse and repeat until num drops below 1000. Then try moving on to the next lower value, D (500). Add D's until you get below 500. And so on. Eventually you will have a Roman numeral equal to the int value. Since you do not care about subtract issues, you will get some technically incorrect answers for subtract cases (for example 9 will result in VIIII not IX).

Good luck. I think we've helped you along quite a bit with this assignment.
Avatar of any

ASKER

nietod, I understand what you are saying, but I dont't want to do subtructions, I only want to do addition in Roman numerals, like IX would be 11 for me. Please help me with what I have. I cannot understand why it doesn't work.
any,i guess you made a copy&paste mistake:
In your main() code you try to find out what char Operation
is(+,-,/,*), but in every case you do  

Roman3= RomanToInt(Roman1)- RomanToInt (Roman2)

so that's always subtruction...



P.s.:If you want to know how to catch illegal roman numbers
take a look at my last posting.
In case of any illegal roman number 0 is returned.
seaxouri, please get a clue!   Your code doesn't count, only "any"'s since he./she is the student! What is important is that "any" leanrs to write the code, not that you can find it somewhere on the web.

>> Start with the resultant 'int' number and a blank string.
>>> Then, if the number is greater than 1000, subtract 1000
>> from the number, and add an "M" to the string. Rinse and
>> repeat until num drops below 1000
There is a better algorithm and it produces correct roman numbers.

>> nietod, I understand what you are saying, but I dont't want to do subtructions,
Are you sure about that?   I really doubt that the assignment was for you to work with "psuedo roman numbers" where IX and XI are both 11.    

>> P.s.:If you want to know how to catch illegal roman numbers
>> take a look at my last posting.
EXPERTS How hard is this to understand?   Any here is actually being good and honestly trying not to cheat and here you guys are posting code that solves his problems and telling him to look at it.    

any,

   I'll give you some points on RomanToInt() if you really want to go that way, bit I think you need to get IntToRoman working the right way first.

You current apraoch isn't too bad.  But as aI pointed out before, it heeds to return a roman number, so it has to return type????

Inside the code you have something like

  while(num>=1000)
  {
      if(num/1000>=1)
      {
          written = written + "M";
          num-=1000;
       }        
   }

   That is the right idea to determine the number of 1000s (M)s in the number.  It will work.   But its not very efficient.   its like you never really need to learn to multiplu.   You can always use repeated addition to achieve the same results as multiplication.  But it may take a while.   The same thing kere.    You are using repeated subtraction because you never learned to divide.    

   If you have a number like 2345 and divide it by 1000, the computer will give you the result 2.   there is a remainder of 345 that it looses (You can use the modulos operator (%) to get the 345).   So this essentually does what your code dos, but in one mathematical step.  Well, it figures out the number of digits of a particular type (like M) in one step.  But then you still have to remove the value associated with the digits found from the value you are converting.   i.e. perform you (num -= 1000) operation in a second step.   Well, I'll show you this, since yoru code really works and there still is plenty for you to do.  

   int NumberofMs;

   NumberofMs = Num /1000;  

   Num -= 1000*NumberOfMs;  // Remove the value associated with the Ms found.

You need to repeat this to find the number of other letters too.   Note that we aren't actually dealing with placing the roman digits in a string yet.   We are just finding out (approximately) how many there are.   The reason is that we need to deal with the fact that 9 iis IX and not VIIII and things like that.  

After you've doen that you need to go through and "corrrect" things like VIIII to IX.   Now this involves looking for any case where a count of digits is too high.   i.e. a count of 4 I's is too high.    When you find a count that is too high you have adjust that count to make it -1 and you have to adjust a number, well digit count for the next higher number as well.  

for example.   If you have  VIIII   You have
CountV = 1
CountI = 4;

Count I is too big.  Make it -1 and add one to Count V.   Note that the number represented stays the same.   You have have 2Vs which is 10 and you have -1 Is, which is -1 so that gives you 9.   So you haven't changed the total value, just how it is represented.    but note that now you have 2 Vs.   You can't have 2 Vs, so it needs to be adjusted too.   (For this reaaon start addjusting with the Is and move towards the Ms.

Why don't you do that much and post what you get done.  
   




     I'm sure you did learn to divide, but the problem is when we humans do it we get two results, the quotient and the remainder.   When the computer does it with the "/" operator we get only the quotient and sometimes that is just not
Opps ignore that last paragraph way at the bottom there.  It was supposed to be edited out.   It drifted off topic.
Avatar of any

ASKER

Where do I call a function?
ASKER CERTIFIED SOLUTION
Avatar of nietod
nietod

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of any

ASKER

Thanks for helping me and explaining to me how everything works!
>seaxouri, please get a clue!
nietod:
Back off a$$. You are out of line. I'd like to tell you to f**k off. I tried being nice, but you are a punk. Keep you bs comments to yourself. Oh, and learn to type proper English.
seaxoure, there are strict guidlines at EE concerning helping students.  You are violating them.  Its one thing to do so when you haven't been told before, but its another to do so after being warned twice in the same question

EE also has strict guidelines concerning the use of profanity.  You can

You might wish to read

Experts Exchange reserves the right to determine what constitutes Internet abuse and objectionable conduct. If Experts
            Exchange believes, in its sole discretion, that a violation of these Guidelines has occurred, it may take responsive action.
            Such action may include, but not be limited to, permanent removal of illegal or inappropriate information or content, or
            suspension or termination of your membership and access to Experts Exchange Service

            * using a Member Name or posting, transmitting or linking to any text or images that are sexually explicit, pornographic,
            violent, racially or ethnically objectionable or grossly offensive to the online community

            * posting, transmitting or linking to defamatory and libelous statements or other statements that would violate any third
            party's privacy or publicity rights

            * posting, transmitting or linking to profane language, descriptions of situations or scenarios considered, in the opinion of
            Experts Exchange, inappropriate for the Experts Exchange membership

            * impersonating any person or using a name that you are not authorized to use

            * planning illegal activities, such as creating computer viruses, building a bomb or counterfeiting money

            * advertising, promoting in any way or offering to sell any goods or services for any commercial purpose

            * soliciting individuals for employment other than in designated areas (for example, within a discussion thread)

            * soliciting individuals to join other services comparable to or competitive with Experts Exchange

            * promoting any products or services that are unlawful at the location at which the content is posted or received

            * posting any content that infringes any third party's intellectual property rights or violates any confidentiality agreements or
            contracts of employment

            * posting, transmitting or linking to statements that are intentionally false or misleading

            * introducing viruses, worms, harmful codes or Trojan horses

            * spamming, flaming or other similar activities

            * misusing the Experts Exchange point system

            * violating the guidelines for academic honesty or other unethical behavior.
nietod,
You're two responses were way out of line and rude.
I should have you banned from here.
Besides, I violated nothing. Let me explain why. This is not a debate, it's an opinion. You have yours, which I disagree with. Here is mine.

Just because a student has a piece of code that may attempt to solve a problem one way, does not mean that we cannot help that student learn other, more efficient ways to write code.  I see too many students graduating from college that come into a project I am working on and try to blast their way through an implementation without regard for writing clean code. There are several good books I can recommend on just this topic if you would like.  Telling a student 'nice try on that piece of code, but here... you just need to bolt this piece of additional code onto your hunk of newbie code to make it work' actually will probably hurt the student later.  I learned a lot from my veteran coworkers that had over 15 years experience. There were many occasions where they basically 'suggested' a rewrite of the entire implementation with some hints as to how to begin. And they were right. I have passed this mthod onto a lot of the newer team members, and been thanked for my 'assistance' on numerous occassions.

Frankly, I see a lot of terrible (ghastly) code on this web site. A lot of our schools teach function, but not implementation efficiency or basic clean code generation, and that is horribly, horribly sad.

Students that want to cheat and carbon copy code that they cannot explain to their mentors are simply hurting themselves and this will be obvious to any instructor (which, I used to be long ago).

Why don't we teach people how to write better code and be better programmers? Anyone can read a song. Let's teach these people how to sing one.


>> Just because a student has a piece of code that may attempt
>> to solve a problem one way, does not mean that we cannot help
>> that student learn other, more efficient ways to write code.
But writing code for a student doesn't really teach them much and it is a violation of accademic honesty.  The assignment was probably not worded like "find code that does XXX"  Most likely the student was supposed to write the code themselves and with minimal amount of help from outside sources.

>> Just because a student has a piece of code that may attempt
>> to solve a problem one way, does not mean that we cannot help
>> that student learn other, more efficient ways to write code.
Writting the code for them isn't teaching them anything.  Its extremely unlikely that the student can even understand it,   (I don't know that I can understand it!)  and most likely if the student turns it in the teacher will know the student is cheating.  And will be easily able to confirm it.   (I know this from 1st hand experience.)   If you want to help the student, try to get them to write the code.

>> Why don't we teach people how to write better code and be better programmers?
I thought that is what I was doing.
>> Writing the code for them isn't teaching them anything.

I disagree. Almost every programming book ever written uses sample code to illustrate key points and concepts.

I am not a babysitter and the people who want help really want help that is easy to see and understand. I will not limit what I explain to people simply because they 'may' be a student that 'may' cheat. That's ridiculous. I also think it is silly to assume that people on this site are all students.  It's possible there are actually people with programming jobs visiting this site and asking legitimate questions. I'm here to help everyone in anyway I can. Everyone. I am not here to judge people guilty of cheating before I submit my help, like some sort of internet teacher's assistant policeman. I like to give people the benefit of the doubt. To think that they have morals and a deep desire to understand a be better at what they do. People that really want to cheat might find it easier paying the local computer geek (I can say it cause I are one) $5 to write their little homework for them. The true seekers are doing it on their own, and coming here for help. Bravo!

There is an entire series of books that use LBE. Which, in case you were not aware, stands for "Learn By Example". How can so many people, books and classes be wrong. I learned (and still learn), and I am sure you did too, most of what I know by example.  For example, when you learned your multiplication tables, did they make you figure it out on your own, or did they teach you to memorize a given table?  Did they then teach you how to perform algebra, or did you have to figure it out on your own?  The only way we grow is to learn what others have figured out, improve on it and teach the result to our children.

>>But writing code for a student doesn't really teach them much and it is a violation of academic honesty.

Show me where providing sample code is a violation of academic honesty. I disagree with your interpretation.
>> Almost every programming book ever written uses sample
>> code to illustrate key points and concepts.
Yes to give examples to get them started.   Then the next step is to get them to write code--usually larger and more comprehensive code.   I doubt you will find any book that gives an example of code and then has the reader try to write the exact same code.

>> I am not a babysitter and the people who want help
>> really want help that is easy to see and understand.
Your code is easy to see, but nearly impossible to understand.   Its increadibly unlikely that a student could understand it without indepth explanations.

>> I will not limit what I explain to people simply because
>> they 'may' be a student that 'may' cheat.
You don't always have to.  But on EE you do.  That has been the rule since nearly it started.  

>> It's possible there are actually people with programming jobs
>> visiting this site and asking legitimate questions.
But accademic questions are usually easy to spot.   This one for example is.  There is no other explanation for the question.   You can't argue that someone is writing a new spreadsheet program and needs help getting started.  Oh and by the way the spread sheet works in roman numbers   :-)    


>> 'm here to help everyone in anyway I can. Everyone. I am not
>> here to judge people guilty of cheating before I submit my help,
>>  like some sort of internet teacher's assistant policeman
You can help people without violating accademic honesty.  I'm not saying you shouldn't help students.  I'm saying you have to do it differently.   You have to help them to reach the solution.  You can't present them with the solution and hope they will understand it.

>> The true seekers are
>> doing it on their own, and coming here for help.
And a lot of cheaters are comming here to.  "Any" is probably more the exception than the rule   He/she obviosuly wants to learn the material.   Many just want the answer.  Many will ask the same question multiple times until some expert funally gives them a complete answer.  Do you think they even try to undertand all the posts made to the other questions?   many will offer exhorbanant points (althoguh nowadays there are point limits) for complete answers to what are fairly simple questions.  And some will ofter to send money!   (My bio no longer lists my fees because I was getting what amounts to bribes a few times a week!)

>> How can so many people, books and classes be wrong. I learned
>> (and still learn), and I am sure you did too, most of what I know
>> by example
You are talking to someone with a good deal of educational psychology and a published author (articles) and currently writting a programming book series.  So I think I have a fairly accurate perspective on this.  The lowest stage of learning is acquisition (of knowledge).  Its good for learning basic principles.  In this case maybe syntax rules, or the basic ideas behind a linked list.   But the problem is that this information tends to be easily lost and not readily used.   The ideas are simply memorized and they are poorly linked to other ideas.  That makes them hard to recall.  An example might be a child memorizing the multiplicaion tables, They a usually unable to recall specific entries, like say 7X7.  Instead they start at the beginning ot peryhaps another point that for some reason stands out in their mind and work forwards to the entry they need.    Without something more this information will be rarely used (because it is difficult to employ) and will be easily forgotten in time.

(in case you are wonderig the higher stages of learning help information to become more accessible and less likely to be forgotten.  For example synthesis forces students to employee several ideas at the same time.  This creates mental links between those ideas and allows the student to access each of the ideas more readily.   For example, teaching the student the the advantages and dissadvatages of each container is mostly acquisition.  But asking them to write an essay that compares and contrasts them will be synthais.  

>>  For example, when you learned your multiplication tables,
LOL  I honestly hadn't even read that far ahead!

>> The only way we grow is to learn what others have figured out,
>> improve on it and teach the result to our children.
But that is not one way of learning.   There are many ways.

>> Show me where providing sample code is a violation of academic honesty
In general samle code would not be a violation.  I often do so.   But sample code that answers the question is clearly a violation.  I use small peices of sample code that demonstrate a particular point or perhaps illustrates one small part of a the solution.  But code that is the solution, or a large part of it, is obviously a violation.  You can't argue it isn't.

(Techniqcally any help we provide might be a violation because a student might be instructed to answer a question without any help--like on an exam.   Regretably ther is nothing we can do about that except trust the student and take some comfort in the fact that at least if they learn the material from us some good (a better good in my opinion--I'm not grade oriented) has come from it.