3 min read

带小数的高精度数的任意进制转换

大学第一学期期末课程设计的一道题,进制转换。

大概思路就是把整数和小数部分分开为 整型 类型,由一个结构体构成。整数部分进制转换模拟人工除法取余,小数部分进制转换模拟人工乘法取整。

numTrans.h
/* Windows 8.1 VS 2013 Pro 编译通过 */
#include <stdio.h>
#define MAXSIZE 10000

typedef struct n{
	short s_integer[MAXSIZE];
	short s_decimal[MAXSIZE];
}NUMBER;

int inputNum(NUMBER * f_num, int f_n);
short charToNum(char f_c);
void numFlip(short * f_num);
void transNum(NUMBER * f_number, NUMBER * f_resultNumber, int f_n, int f_m);
void printNum(short * f_num);
void printTheWholeNum(NUMBER * f_num, int f_m);
numTrans.c
/* Windows 8.1 VS 2013 Pro 编译通过 */

#include "numTrans.h"

char numBase[36] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
int i, j;
int isHightestNum = 1;
int haveDecimalNum = 0;
int haveIntegerNum = 0;

int main(){
	NUMBER number, resultNumber;
	int n, m;
	printf("请输入数字的进制类型:\n");
	scanf("%d", &n);
	fflush(stdin);
	//高精度数总是以位数从低到高排在数组里面,如有计算需要翻转,计算完毕再翻转回来,以免混乱。
	printf("请输入这个整数:\n");
	if (!inputNum(&number, n)){
		printf("输入错误\n");
		return 0;
	}
	printf("请输入需要转换的进制类型:\n");
	scanf("%d", &m);
	transNum(&number, &resultNumber, n, m);
	printTheWholeNum(&resultNumber, m);
	return 0;
}

int inputNum(NUMBER * f_num, int f_n){
	char tempChar;
	short tempNum;
	*(f_num->s_integer) = 0;
	*(f_num->s_decimal) = 0;
	while ((tempChar = getchar()) != '\n'){
		if (isHightestNum){
			if (tempChar == '0'){
				continue;
			}else{
				isHightestNum = 0;
			}
		}
		if (!haveDecimalNum && tempChar == '.'){
			haveDecimalNum = 1;
		}
		if ((tempNum = charToNum(tempChar, f_n)) == -1){
			return 0;
		}
		if (haveDecimalNum){
			++(*(f_num->s_decimal));
			*(f_num->s_decimal + *(f_num->s_decimal)) = tempNum;
		}else{
			++(*(f_num->s_integer));
			*(f_num->s_integer + *(f_num->s_integer)) = tempNum;
		}
	}
	if (haveDecimalNum){
		numFlip(f_num->s_decimal);
	}

	if (*(f_num->s_integer) != 0){
		haveIntegerNum = 1;
		numFlip(f_num->s_integer);
	}
	return 1;
}

short charToNum(char f_c, int f_n){
	short tempNum;
	if (f_c >= 'a' && f_c <= 'z'){
		tempNum = (short)f_c - 'a' + 10;
	}else if (f_c >= 'A' && f_c <= 'Z'){
		tempNum = (short)f_c - 'A' + 10;
	}else if (f_c >= 48 && f_c <= 57){
		tempNum = (short)f_c - '0';
	}
	if (tempNum >= f_n){
		return -1;
	}else{
		return tempNum;
	}
}

void numFlip(short * f_num){
	short temp;
	for (i = 0; i < *f_num / 2; i++){
		temp = *(f_num + 1 + i);
		*(f_num + 1 + i) = *(f_num + *f_num - i);
		*(f_num + *f_num - i) = temp;
	}
}

void transNum(NUMBER * f_number, NUMBER * f_resultNumber, int f_n, int f_m){
	short f_tempNum[MAXSIZE];
	short f_num[MAXSIZE];
	//*f_tempNum = 0;
	*(f_resultNumber->s_decimal) = 0;
	*(f_resultNumber->s_integer) = 0;
	if (haveIntegerNum){
		for (j = 1; j <= *(f_number->s_integer); j++){
				*(f_tempNum - 1 + j) = *(f_number->s_integer + j);
		}
		int len = *(f_number->s_integer);
		while(len) {	//每一轮手动模拟除法
	        for(i = len - 1; i >= 1; --i) {
	        	*(f_tempNum + i - 1) += *(f_tempNum + i) % f_m * f_n;
				*(f_tempNum + i) /= f_m;
	        }
	        *(f_resultNumber->s_integer + ++(*(f_resultNumber->s_integer))) = *f_tempNum % f_m;
	        *f_tempNum /= f_m;
	        while(len > 0 && !*(f_tempNum + len - 1)){
	            len--;
	        }
	    }
	}
	if (haveDecimalNum){
		for (i = 0; i <= *(f_number->s_decimal); i++){
			*(f_num + i) = *(f_number->s_decimal + i);
		}
		*f_tempNum = *(f_number->s_decimal);
		int len = *f_tempNum, k = 0, s = 0, carry, flag = 1;  // k 如果进制转换死循环,用于控制小数点位数
		*(f_tempNum + len + 1) = 0;
		*(f_tempNum + len + 2) = 0;
		while (1){
			++k;
			for (i = 1; i <= len; i++){
				*(f_tempNum + i) = 0;
			}
			for (i = 1; i <= len; i++){
				*(f_tempNum + i) += *(f_num + i) * (f_m % 10);
				*(f_tempNum + i + 1) += *(f_tempNum + i) / 10;
				*(f_tempNum + i) %= 10;
			}
			for (i = 1; i <= len; i++){
				*(f_tempNum + i + 1) += *(f_num + i) * (f_m / 10);
				*(f_tempNum + i + 2) += *(f_tempNum + i + 1) / 10;
				*(f_tempNum + i + 1) %= 10;
			}

			*(f_resultNumber->s_decimal + ++(*(f_resultNumber->s_decimal))) = *(f_tempNum + len + 1) + *(f_tempNum + len + 2) * 10;
			*(f_tempNum + len + 1) = 0;
			*(f_tempNum + len + 2) = 0;
			for (i = 0; i <= len; i++){
				*(f_num + i) = *(f_tempNum + i);
			}
			for (i = 1; i <= len; ++i){
				if (*(f_tempNum + i) != 0){
					flag = 0;
				}
			}
			if (flag){
				break;
			}
			flag = 1;
			if (k == 16){
				break;
			}
		}
		numFlip(f_resultNumber->s_decimal);
	}

}

void printNum(short * f_num){
	for (i = *f_num; i >= 1; i--){
		printf("%c", *(numBase + *(f_num + i)));
	}
}

void printTheWholeNum(NUMBER * f_num, int f_m){
	if (f_m == 16){
		printf("0x");
	}else if (f_m == 8){
		printf("0");
	}
	if (*(f_num->s_integer)){
		printNum(f_num->s_integer);
	}else{
		printf("0");
	}
	if (*(f_num->s_decimal)){
		printf(".");
		printNum(f_num->s_decimal);
	}
	printf("\n");
}