2013年7月22日月曜日

Cで固定小数点

C語で固定小数点の文字列化です
string.h関数が必要になります 使ってるのはstrlenだけなので適当に実装してください
関数は2つあります
strAddは再帰を使ってます
場合によっては30回以上再帰します

以下コード


int strAdd(char *string, char ch, int pos) {
if (pos < 0) { return(1); }
if (string[pos] == '.') { strAdd(string, ch, pos - 1); }
int num = (string[pos] - '0') + (ch - '0');
if (num < 10) { string[pos] = num + '0'; return(0); }
string[pos] = (num - 10) + '0';
return(strAdd(string, '1', pos - 1));
}

char*Q2A(uint32_t val1, uint32_t val2) {
static char string[60];
const  char*dataP1[] = {
"1", 
"2", 
"4", 
"8", 
"16", 
"32", 
"64", 
"128", 
"256", 
"512", 
"1024", 
"2048", 
"4096", 
"8192", 
"16384", 
"32768", 
"65536", 
"131072",
"262144", 
"524288", 
"1048576", 
"2097152", 
"4194304", 
"8388608", 
"16777216", 
"33554432", 
"67108864", 
"134217728", 
"268435456", 
"536870912", 
"1073741824", 
"2147483648", 
"4294967296", 
};
const  char*dataM1[] = { 
"00000000023283064365386962890625",
"0000000004656612873077392578125",
"000000000931322574615478515625",
"00000000186264514923095703125",
"0000000037252902984619140625",
"000000007450580596923828125",
"00000001490116119384765625",
"0000000298023223876953125",
"000000059604644775390625",
"00000011920928955078125",
"0000002384185791015625",
"000000476837158203125",
"00000095367431640625",
"0000019073486328125", 
"000003814697265625",  
"00000762939453125",
"0000152587890625", 
"000030517578125", 
"00006103515625", 
"0001220703125", 
"000244140625", 
"00048828125", 
"0009765625",
"001953125", 
"00390625", 
"0078125", 
"015625", 
"03125", 
"0625", 
"125", 
"25", 
"5",
};
int i, j;
int pointPos = 20;
for (i = 0; i < ((sizeof(string) / sizeof(string[0])) - 1); i++) { string[i] = '0'; }
string[i] = '\0';
string[pointPos] = '.';
i = 0;
while (i < sizeof(val1) * 8) {
if ((val1 >> i) & 1) {
int len = strlen(dataP1[i]);
j = len - 1;
do { strAdd(string, dataP1[i][j], pointPos - (len - j)); } while (j--);
}
i++;
}
i = 0;
while (i < sizeof(val2) * 8) {
if ((val2 >> i) & 1) {
int len = strlen(dataM1[i]);
j = len - 1;
do { strAdd(string, dataM1[i][j], pointPos + j + 1); } while (j--);
}
i++;
}
i = (sizeof(string) / sizeof(string[0])) - 2;
while (string[i] == '0') { i--; }
if (string[i] == '.') { i++; }
string[i + 1] = '\0';
i = j = 0;
while (string[i] == '0') { i++; }
if (string[i] == '.') { i--; };
do { string[j++] = string[i]; } while (string[i++]);
return(string);

}

32bitの正数と32bitの少数を引数に渡します
符号はなく 負数は扱えません
扱える範囲は4294967295.99999999976716935634613037109375から0.00000000023283064365386962890625で 双方に0を設定すれば0.0になります
2^-32は0.00000000023283064365386962890625で
実際の精度は9桁程度です
テーブルを増やし、引数を増やせばもっと広い範囲で使うこともできます

まだバグとかは色々あると思いますがとりあえずある程度は正常に表示できます

0 件のコメント:

コメントを投稿