ローマ数字→アラビア数字自動変換


今、気づきました。

アラビア数字から、ローマ数字へ変換できるだけでは、間が、抜けているということを、です。

その逆が出来なければ、あほ。

 

従って、その逆を行うために、ローマ数字からアラビア数字へ変換してやる方法を、考えなくてはなりません。

で、東北本線(高崎線かも)の電車の中で考えました。

 

基本的には、次のようになると思います。

  1. ローマ数字をあらわす文字かどうかを判別する。
  2. 文字があらわす数を逐次加算する。
  3. 左から右へ数字が小さくなっていってるかどうか判別する。

ただ、例外があります。

  1. 減算に配慮する。
  2. 減算時は被減算対象が10倍または5倍かをチェック。
  3. 減算対象が5の倍数ではないことをチェック。

    などなど。

こんなところでしょうか。

 

上記の要求にしたがって記述したら、このようになりました。

見れば分かりますが、言語はCです。

かなり汚いソースですし、洗練されていないロジックなので恥ずかしいのですが、あくまでもサンプルですので。

 

で、 Java に移植したソースが、こちらにあります。

Java 版は、 main関数もつけといたので、コンパイルすればそのまま実行できます。

Java なので、当然ながら、javaが必要です。

Sun からダウンロードするなりして、適当に入手して下さいませ。

 

で、これを、この前作ったアラビア数字→ローマ数字自動変換モジュールとくみあわせてやれば、自動判別機能付きの相互変換も出来る事になります。

 

ちなみに、これのGUIの実行モジュールは、めんどくさいので端折りました。

相互変換モジュールのほうは作るつもりなので、そちらを見て下さいませ。

 

<>


ふろく1

C言語によるローマ数字→アラビア数字変換ロジック例

------ここから-----

#include <stdio.h>
#include <ctype.h>
#include <string.h>

#define null NULL

/*
	(c)1999 A.Matsuda 
	arabic.c
*/

struct{
	int c;
	int v;
}tbl[] = {
	{ 'm', 1000 },
	{ 'd',  500 },
	{ 'c',  100 },
	{ 'l',   50 },
	{ 'x',   10 },
	{ 'v',    5 },
	{ 'i',    1 },
	{  -1  , -1 },
};

int chkv( int c )
{
	int i;
	for( i = 0 ; ; i++ ){
		if( tbl[i].c == -1 ){
			break;
		}
		if( toupper(tbl[i].c) == toupper(c) ){
			return 1;
		}
	}
	return 0;
}
int getv( int c )
{
	int i;
	for( i = 0 ; ; i++ ){
		if( tbl[i].c == -1 ){
			break;
		}
		if( toupper(c) == toupper(tbl[i].c) ){
			return tbl[i].v;
		}
	}
	return -1;
}

int arabic( char* buf , int* val )
{
	int prev = 0;
	int current = 0;
	int i;
	int cnt = 0;

	if( buf == null || val == null ){
		return 1;
	}
	*val = 0;
	
	for( i = 0 ; i < strlen( buf ) ; i ++ ){
		if( chkv(buf[i]) ){
			current = getv( buf[i] );

			if( prev == current){
				cnt++;
			}
			else{
				if( prev < current && cnt >= 1 ){
					/* 2回以上引かれる数より小さな数が続いた後に減算を行う事はない */
					return -2;
				}
				cnt = 0;
			}
			if( current > prev && prev != 0 ){
				if( prev*5 != current && prev*10 != current ){
					return -2;
				}
				if( prev == 5 || prev == 50 || prev == 500 ){
					return -2;
				}
				*val -= prev*2;
				*val += current;
				prev = current - prev;
			}
			else{
				/* 一度減算をおこなったら、currentよりも小さな値であるべき */
				if( prev != 0 && (( (prev%9) == 0 ) && (prev/9) <= current) ) {
					return -2;
				}
				if( prev != 0 && ( prev == 4 || prev == 40 || prev == 400 ) && ( ( prev / 4 ) <= current ) ){
					return -2;
				}
				if( ( prev == 5 || prev == 50 || prev == 500 ) && (cnt >= 1 ) ){
					return -2;
				}
				
				*val += current;
				prev = current;
			}
		}
		else{
			return -3;
		}
	}
	
	return 0;
}

------ここまで-----

 

ソースプログラムのダウンロードはこちらをクリックして下さい。

<>


つかいかた

つかいかたのごせつめい。

  1. コンパイルする。
  2. main関数を書く。
  3. arabic()をコールする。

 

関数のつかいかたのごせつめい。

書式

引数

  1. char* buf
    変換元ローマ数字文字 (IN)
  2. int* val
    変換後の10進数値(OUT)
    異常終了時の値は不定。

戻値 int


  1. 正常終了
  2. 1
    引数が不正

  3. ローマ数字構文が不正

  4. 異文字種が混入

 

 

<>


ご注意

 

<>


ふろく2

Javaによるローマ数字→アラビア数字変換ロジック例

 

------ここから-----

/*
	arabic.java
	(c)1999 A.Matsuda 
*/
import	java.awt.*;
import	java.awt.event.*;
import	java.awt.Toolkit.*;
import	java.applet.*;
import	java.util.*;
import	java.lang.*;
import	java.text.*;
import	java.lang.System.*;

public class arabic
{
	static final char delimiter = (char)-1;
	class elem{
		char c;
		int v;
		public elem(char c, int v){
			this.c = c;
			this.v = v;
		}
		public char getChar()
		{
			return c;
		}
		public int getVal()
		{
			return v;
		}
	};
	elem tbl[]={
		new arabic.elem( 'm', 1000 ),
		new elem( 'd',  500 ),
		new elem( 'c',  100 ),
		new elem( 'l',   50 ),
		new elem( 'x',   10 ),
		new elem( 'v',    5 ),
		new elem( 'i',    1 ),
		new elem(  delimiter  , -1 ),
	};
	boolean chkv( char c )
	{
		int i;
		for( i = 0 ; ; i++ ){
			if( tbl[i].getChar() == delimiter ){
				break;
			}
			if( tbl[i].getChar() == c ){
				return true;
			}
		}
		return false;
	}
	int getv( char c )
	{
		int i;
		for( i = 0 ; ; i++ ){
			if( tbl[i].getChar() == (char)-1 ){
				break;
			}
			if( c == tbl[i].getChar() ){
				return tbl[i].getVal();
			}
		}
		return -1;
	}

	int arabic( String buf ) throws Exception
	{
		int prev = 0;
		int current = 0;
		int i;
		int val = 0;
		int cnt = 0;
 		
		buf.trim();
		buf = buf.toLowerCase();
		
		for( i = 0 ; i < buf.length() ; i ++ ){
			if( chkv( buf.charAt( i ) ) == true ){
				current = getv( buf.charAt( i ) );

				if( prev == current){
					cnt++;
				}
				else{
					if( prev < current && cnt >= 1 ){
						//2回以上引かれる数より小さな数が続いた後に減算を行う事はない
						throw new Exception("書式が不正です");
					}
					cnt = 0;
				}
				if( current > prev && prev != 0 ){
					if( prev * 5 != current && prev * 10 != current ){
						throw new Exception("書式が不正です");
					}
					if(  prev == 5 || prev == 50 || prev == 500 ){
						throw new Exception("書式が不正です");
					}
					val -= prev * 2;
					val += current;
					prev = current - prev;
				}
				else{
					//一度減算をおこなったら、currentよりも小さな値であるべき
					if( prev != 0 && ( ( ( prev % 9 ) == 0 ) && ( ( prev / 9 ) <= current) ) ) {
						throw new Exception("書式が不正です");
					}
					if( prev != 0 && ( prev == 4 || prev == 40 || prev == 400 ) && ( (prev / 4) <= current ) ){	//減算が行われた直後に同じ桁の数は並ばない。
						throw new Exception("書式が不正です");
					}
					if( ( prev == 5 || prev == 50 || prev == 500 ) && (cnt >= 1 ) ){
						throw new Exception("書式が不正です");
					}
					
					val += current;
					prev = current;
				}
			}
			else{
				throw new Exception("不正な文字が含まれています");
			}
		}
		
		return val;
	}

	public static void main( String arg[] )
	{
		int i;
		int val;
		arabic arabic = new arabic();
		
		for( i = 0 ; i < arg.length ; i++ ){
			try{
				val = arabic.arabic( arg[ i ] );
			}
			catch( Exception e ){
				System.out.println( e.getMessage() );
				continue;
			}
			System.out.println( arg[i] + "-->" + new Integer(val).toString() );
		}
	};
};

------ここまで-----

 

ソースプログラムのダウンロードはこちらをクリックして下さい。

<>


つかいかた

つかいかたのごせつめい。

  1. API1.1以上をサポートしている環境でコンパイルする。
  2. 実行する。

引数のあたえかた

  1. コマンドラインに、アラビア数字を好きなだけならべる。
    Ex) $ java arabic 931 324 123 43 223

クラスの使い方のご説明。

  1. インスタンスを生成する。
  2. arabic.arabic()をcallする。

 

class arabic:
int arabic( String buf ) throws Exception

引数

戻値 int

付記

 

 

<>


ご注意

 

<>


<ホームページへ> <ローマ数字変換へ> <ローマ数字→アラビア数字自動変換へ> <アラビア数字←→ローマ数字相互自動変換へ>

Copyright © MCMXCIX Ayumi Matsuda All rights reserved.