Data_Structure/作業/老師解答/unit2/poly-integer-root-v2.c
2025-01-20 21:25:33 +08:00

125 lines
3.4 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
Program: poly-integer-root-v2.c (Report comments/bugs to chikh@yuntech.edu.tw)
Function: 計算多項式的整數根,程式接受鍵盤輸入的多項式,輸出結果把輸入的多項式以最精簡的形式呈現(係數與指數若為1可省略)
,且需顯示解得的整數根;若整數根不存在,則顯示訊息告知
Notes:
1) 本程式透過鍵盤讀入多項式而poly-integer-root-v1.c把多項式直接設於程式內彈性較受限
2) 程式接受鍵盤輸入的形式可為
1x^2-100x^0
1x^3-2x^2-1x^1+2x^0
1x^3-7x^2+4x^1+12x^0
1x^4+3x^3-66x^2+52x^1+120x^0
3x^4+9x^3-198x^2+156x^1+360x^0
*/
#include <stdio.h> /* for scanf(), sscanf() */
#include <stdlib.h> /* for malloc(), abs() */
#include <math.h> /* for pow() */
#define MAX 256
void compact(char str[]) /* 移除str當中的空白使變得緊實 */
{
int i, j;
for (i = j = 0; str[i]; i++, j++) {
for (; str[i]==' '; i++);
str[j] = str[i];
}
str[j] = '\0';
printf("\n移除空白後的字串:%s\n",str);
}
int readPoly(int p[]) /* 讀入運算式字串,把各項之指數與係數分別儲存於陣列,回傳非零項個數 */
{
int i = 1, argCount;
char str[MAX];
gets(str); /* 建議改用 fgets(str,MAX,stdin) 以避免造成輸入資料過長而造成鍵盤緩衝區爆掉產生錯誤 */
compact(str); /* 移除str當中的空白使變得緊實 */
do {
if ((argCount=sscanf(str,"%dx^%d%s",&p[i+1],&p[i],str))==2) break; /* 從str只讀到2個數據之後再也沒有東西可消化(轉存入str),意味字串已讀盡,將跳離迴圈 */
if (argCount == 1) { /* 最末項讀到常數表示式,譬如 3 或 -5 (未寫成3x^0仍能處理) */
p[i] = 0;
break;
}
i += 2;
} while (1);
return (p[0] = (i+1)/2); /* 回傳非零項個數 */
}
int findRoot(int p[], int q[]) /* 找根所得解存入q[],回傳根的個數 */
{
int r, c = 0, i, j, k, sum;
int sign[2] = {1,-1};
if (p[2*p[0]]%p[2] != 0) return 0; /* 最末項的係數不能被最高階項的係數整除,則不存在整數解 */
r = abs(p[2*p[0]]/p[2]); /* 正規化後最高階項之係數為1最末項的係數為r */
for (i = 1; i <= r; i++) { /* 考慮能整除r的因數i須注意正負號 */
if (r%i != 0) continue; /* 不能整除r的i將略過繼續考慮下一個i */
for (j = 0; j < 2; j++) { /* j為0代表考慮+i的情境j為1代表考慮-i的情況 */
for (sum = 0, k = 1; k <= 2*p[0]; k+=2) /* 計算每一項的結果值(係數*x^指數)並累加到sum之中 */
sum += p[k+1]*(int)(pow(sign[j]*i,p[k]));
if (sum == 0) q[c++] = sign[j]*i; /* bingo! 發現合乎條件的整數根將其寫入q陣列 */
}
}
return c;
}
void show(int p[], int n, int mode)
{
int i;
if (mode == 0) { /* 顯示方程式 */
printf("方程式p(x)= ");
for (i = 1; i <= n; i += 2) {
if (abs(p[i+1])>1) /* 係數>1或<-1則顯示該係數值 */
printf("%s%d",p[i+1]>1? "":"\b",p[i+1]); /* 若係數為負值,把前導的+號塗掉 */
else if (p[i+1]==-1) /* 係數為-1僅顯示-號即可 */
printf("%s",p[i]==0? "\b-1":"\b-");
else
printf("%s",p[i]==0? "1":"");
switch(p[i]) {
case 0:
printf("+");
break;
case 1:
printf("x+");
break;
default:
printf("x^%d+",p[i]);
}
}
printf("\b ");
}
else { /* mode==1顯示所得解 */
for (i = 0; i < n; i++) printf("%d、",p[i]);
if (n > 0) printf("\b\b ");
}
}
int main()
{
int p[101] = {0};
int c, *q;
printf("\n*** 解多項式之整數根 ***\n\n輸入多項式 ==> ");
c = readPoly(p); /* 鍵盤讀取多項式子 */
q = (int *)malloc(p[1]*sizeof(int)); /* p[1]紀錄最高階項之指數,依此值創建足夠元素空間的陣列存放所求得的整數根 */
show(p,2*p[0],0);
c = findRoot(p,q);
if (c > 0) {
printf("\n\n解得整數根為:");
show(q,c,1);
}
else
printf("\n\n整數根不存在\n");
free(q);
return 0;
}