audiofan wrote:
會嗎? 人家有減65...(恕刪)

減65只是把陣列的第一個值offset回0而已,佔的記憶體大小並沒影響啊
XD使者 wrote:
如果是我
我也是抓...(恕刪)


謝謝幫我解釋@@"

這樣就是我寫的那一段程式碼



至於第二題,只能說資訊太少了,沒有辦法寫的很完整。

#include<stdio.h>
#include<stdlib.h>
int main()
{
int RoN[7]={1000,500,100,50,10,5,1};
char RoC[7]={'M','D','C','L','X','V','I'};
int num,i,j;

scanf("%d",#);

for( ; ; )
{
for(i=0;i<7;i++)
{
if(num>=RoN[i])
{
num-=RoN[i];
printf("%c",RoC[i]);
break;
}

for(j=6;j>i;j--)
{
if((i==0&&j==1)||(i==2&&j==3)||(i==4&&j==5))
break;
//printf("%d %d %d\n",i,j,num);

if(num>=(RoN[i]-RoN[j]))
{
num-=(RoN[i]-RoN[j]);
printf("%c%c",RoC[j],RoC[i]);
}
}
}

if(num==0)
break;
}

}
是我誤解了box59453大大的想法了嗎?

以下我把他的想法實作出來,用gcc編譯後執行無誤。
除了輸入的buffer外,只要27 bytes。 (多的1 byte用來防呆)

#include <stdio.h>

char toupper (char c)
{
if (c >= 'a' && c <= 'z')
return c - 0x20;
else if (c >= 'A' && c <= 'Z')
return c;
else
return 26;
}

int main ()
{
int i;
char a[128] = {0};
int countnum[27] = {0};

fgets(a, sizeof a, stdin);

for (i = 0; i < sizeof a; i++)
countnum[toupper(a[i]) - 65]++;

for (i = 0; i < 26; i++)
if (countnum[i] != 0)
printf("%c: %d ", 65 + i, countnum[i]);
return 0;

}

結果:
ADAaEVSzaZ
A: 4 D: 1 E: 1 S: 1 V: 1 Z: 2

用一個toupper function,好處是可以加入一些防呆的動作。如果輸入只會有A~Z or a-z,
就不用toupper()了,用我前面的方法,and 0x1f 把大小寫混在一起會更快。

daniel35 wrote:
第二題假設輸入數字是1234,就除以1000,做計數,剩下的餘數再除500,做計數,是這樣子嗎?,...(恕刪)


自己想想9999 跟99999怎麼用手寫出來
再把你的邏輯寫成程式即可
daniel35 wrote:
2.輸入一數字,以羅馬數字的方式輸出。(羅馬數字中M﹦1000, D=500,C﹦100,L=50,X=10,V=5,I=1)



其實第二題還蠻有趣的哩。



考慮 1~10 好了:
I, II, III, IV, V, VI, VII, VIII, IX, X...

考慮 10~100:
X, XX, XXX, LX, L, LX, LXX, LXXX, XC, C...

但是考慮 48, 49, 50, 98, 99, 100:
XLVIII, IL, L, XCVIII, XCIX, C...

最後的 49 和 99 很容易讓人中招吧?



我在網路上找到了羅法數字的規則,給大家參靠一下:



羅馬數字系統源自伊特魯利亞文(Etruscan),只用7個符號,包括I(1),V(5),X(10),L(50),C(100),D(500),M(1000)。羅馬數字並沒有0。可是按照下面的規則卻可以表示任意自然數。 一般認為這套記數系統只要用來記數卻不作演算。

 
(1)重複數次決定倍數:1個羅馬數字重複幾次,就表示這個數的幾倍。例如: ⅩⅩⅩ=30.

(2)右加左減:在一個較大的羅馬數字的右邊記上一個較小的羅馬數字,表示大數字加小數字。
在一個較大的數字的左邊記上1個較小的羅馬數字,表示大數字減小數字。
但是,左減不能跨越一個位數。比如,99不可以用IC表示,而是用XCIX表示。此外,左減數字不能超過1位,比如8寫成VIII,而非IIX。同理,右加數字不能超過3位,比如14寫成XIV,而非XIIII。

(3)數字上加橫線乘千或乘百萬:在1個羅馬數字的上方加上1條橫線或者在右下方寫M,表示將這個數字乘以1000,即是原數的1000倍。同理,如果上方有2條橫線,即是原數的1000000倍。

(4)數碼限制:同樣數碼最多只能出現3次,如40不能表示為XXXX,而要表示為XL。但是,由於IV是古羅馬神話主神朱庇特(IVPITER,古羅馬字母沒有J和U)的首字,因此有時用IIII代替IV。 一般大時鐘(不包刮英國大笨鐘)的時刻就以IIII代替IV,也可能是為了字體的對稱性。



所以根據上面的規則,我整理幾個可能的實作規則:
(1)由阿拉伯數字的千位數開始取代字串,然後是百位數,依此類推。
(2)用陣列來記錄羅馬數字字串,比如說 { "", "I", "II", "III", "IV", ... },來增進程式效能。(空字串就是零)
(3)注意特殊規則的數字,另外處理。比如說 49。
(4)輸入參數的邊界值在哪邊?也許是 3999~1?
(5)也許我會寫兩個 function,一個處理 999~100,另一個處理 99~0?還是要再分成 99~50 與 49~0 呢?或是結合第二個規則然後採用遞迴的方式實作呢?
疑問已經得到解答嚕!!!自爆以免打擾各位研究C語言^^
gemini89a wrote:
其實第二題還蠻有趣的...(恕刪)

喝太多茶,睡不著....試了一下,1~9999應該沒問題。
(假設5000=小v,10000=小x)

#include <stdio.h>
#define roman(n1, n5, n10) \
{#n1, #n1#n1, #n1#n1#n1, #n1#n5, #n5, \
#n5#n1, #n5#n1#n1, #n5#n1#n1#n1, #n1#n10, #n10}

int power10[] = {1000, 100, 10, 1};

char roman_num[][10][5] = {
roman(M, v, x),
roman(C, D, M),
roman(X, L, C),
roman(I, V, X),
};
#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(arr[0]))

int main (void)
{
int num;
int i;
int index;

scanf("%d", #);

for (i = 0; i < ARRAY_SIZE(roman_num); i++) {
index = num / power10[i];
num %= power10[i];
if (index) printf("%s", roman_num[i][index - 1]);
}

printf("\n");
return 0;

}

只要知道正確的羅馬符號,再加入roman_num陣列就可以擴充到萬、十萬、百萬(如果有的話)。
有第二題啊XDDD(炸飛)
第二題
我是先把特殊的拿出來做比較(像上面有些大大說的4..9..49..90..490..900<=其實我也不是很清楚= =|||)
不成立就減最大值
減幾次就是有幾個
如果不能減就用小一次的減
當然每次都要先比對特殊的
用迴圈去減
電腦做乘除法運算比加減運算慢很多
所以就用計數的方式去做吧
---------------------------------------------分隔線---------------------------------------------
不過我還會比較喜歡用副程式方式去寫
每一種狀況都要考慮一下
這樣程式就會比較有結構
還有就是
程式寫的多少不代表一個程式的好壞
寫程式要注重的東西是時間和空間的利用
並不是程式的長短
程式長指令多不太表效率差
要考慮每個指令
在電腦下面的執行效率
---------------------------------------------分隔線---------------------------------------------
以上是中毒太深XD
各位大大不要砲轟我啊XDDD

audiofan wrote:

喝太多茶,睡不著....(恕刪)



audiofan 兄程式技巧很夠,看得出來是練家子喔!

不過小弟我還是有幾點小小的地方想跟 audiofan 兄討論一下:
1.輸入 49 時會出現 XLIX 還是 IL 呢?
2.如果將來要擴充這段程式能處理的數字位數,除了要改 roman_num 外,是不是還得修改 power10?
3.用這種方式能處理的數字最大是多少呢?輸入負數時會出現什麼情況呢?
4.雖然處理的數字位數不多,用到的除法和餘數不是很多... 不過有沒有辦法可以不用到除跟餘數呢?

哈,說這些不是說 audiofan 兄的程式有什麼問題,
只是我覺得這些問題也是很有趣的喔!


XD使者 wrote:
電腦做乘除法運算比加減運算慢很多
所以就用計數的方式去做吧



XD使者兄,您可以寫段程式來比較加減乘除的運算速度,
結果可能會超乎您的想像喔!

現在的 CPU 真的都很讚呢,
為了去掉乘法而去做最佳化,有時候反而會有反效果喔。
數字轉羅馬一個簡單原則,每位數分開處理,簡單來說
49 = 40 + 9 (不是50-1)
99 = 90 + 9 (不是100-1)
999 = 900 + 90 + 9 (不是1000-1)
這樣一來就很容易了,最直覺的就建表100~900,10~90,1~9
照順序串起來就是了

進階一點
百位數 (M,D,C)
十位數 (C,L,X)
個位數 (X,V,I)
數字部份都是套同一套法則,只是位數不同符號不同而已
例 7=VII,70=LXX,700=DCC 都是該位數 第二符號一個 + 第三符號兩個
所以弄個1~9的取符號表,然後依位數不同,拿不同符號組來取罷了

想到這裡,或許從羅馬數字轉回阿拉伯數字會比較有趣一點...
文章分享
評分
評分
複製連結

今日熱門文章 網友點擊推薦!