Data_Structure/作業/老師解答/unit2/poly-integer-root-v3.c
2025-01-20 21:30:53 +08:00

131 lines
3.5 KiB
C
Raw Permalink 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-v3.c (Report comments/bugs to chikh@yuntech.edu.tw)
Function: 計算多項式的整數根,程式接受鍵盤輸入的多項式,輸出結果把輸入的多項式以最精簡的形式呈現(係數與指數若為1可省略)
,且需顯示解得的整數根;若整數根不存在,則顯示訊息告知
Notes:
1) 改進poly-integer-root-v2.c、修正二版程式第58行的誤判使能盡可能地求得整數根而非令所有根均為正數才算有完整整解
2) 本程式可處理多項式不存在常數項的情境
3) 接受鍵盤輸入的形式可為
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
1x^2-1x^1
2x^ 3 -201 x^2+ 97 x^1 +300
2x^12-195x^11-500x^10
6x^4 - 1x^3 -25x^2 + 4x^1 + 4
*/
#include <stdio.h>
#include <stdlib.h> /* for malloc() */
#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]-1] != 0) { /* 最低階項的指數 >= 1則0為可能解 */
if ((i=p[2*p[0]-1]) > 0) q[c++] = 0; /* 最低階項的指數設為i */
for (j = 1; j < 2*p[0]; j+=2) p[j] -= i;/* 所有項次的指數減去i */
}
r = abs(p[2*p[0]]); /* 取出最低階項之係數 */
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-");
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;
}