開発ターゲットのCPUがシンプルで、isnan()をサポートしていません。
isnanもどきを自作する必要があって、それっぽい関数ができつつあります。
isnan(x)について調べてみたのですが、x が NaN ならば整数非ゼロを返す。
とネット上にありました。
NaNなら1を、NaNでなければ0を返すつもりで設計していますが、
整数非ゼロって何でしょうか。
isnan関数の返り値
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 15年前
- 住所: 東海地方
- 連絡を取る:
Re: isnan関数の返り値
整数非ゼロっては0以外の整数って意味ですね。
ちなみにisnanはC99に対応していないと使えません。
なので、コンパイラの問題だったり、gccならオプションしだいで使えたりします。
ちなみにisnanはC99に対応していないと使えません。
なので、コンパイラの問題だったり、gccならオプションしだいで使えたりします。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
-
ぽんた
Re: isnan関数の返り値
YuOさん、softyaさん、ありがとうございます。
使う側の利便によって返り値は変わるんですね。
Cの規格は厳密に定義されているように見えますが
時にユーザー任せの所もあるのが不思議です。
何か由来があるのでしょうね。
isnan関数については
#define isnan(x) ((x) != (x))
という荒業もあるようですね。あまり使いたくありませんが・・・
32bitなのでビットマスクができませんから
上位16bitと下位16bitに分離して共用体に納めてから
1bitごと個別に取り出して判定してみます。
多分、解決するでしょうw
使う側の利便によって返り値は変わるんですね。
Cの規格は厳密に定義されているように見えますが
時にユーザー任せの所もあるのが不思議です。
何か由来があるのでしょうね。
isnan関数については
#define isnan(x) ((x) != (x))
という荒業もあるようですね。あまり使いたくありませんが・・・
32bitなのでビットマスクができませんから
上位16bitと下位16bitに分離して共用体に納めてから
1bitごと個別に取り出して判定してみます。
多分、解決するでしょうw
-
ぽんた
Re: isnan関数の返り値
とりあえず、isnan()をサポートしないコンパイラに備えてタイニーな t_isnan() を作りました。
スキルがないのでとても恥ずかしいのですが、もっとカッコいいアルゴリズムがあったら教えて欲しいです・・・
スキルがないのでとても恥ずかしいのですが、もっとカッコいいアルゴリズムがあったら教えて欲しいです・・・
#include <stdio.h>
struct s_tag {
short s1;
short s2;
};
union u_tag {
struct s_tag s_acc;
float f;
} u_acc;
int main(void)
{
int i, bit, ans;
int signif = 0;
int chr1[16], chr2[16];
long int ret;
char str1[17], str2[17], *e;
float num = 0.0, den = 0.0;
u_acc.f = 0.0;
printf("num:"); scanf("%f", &num); //分子
printf("den:"); scanf("%f", &den); //分母
u_acc.f = num / den;
/* 上位16bitを抽出 */
for (i=15; i>=0; i--){
bit=(u_acc.s_acc.s2>>i)&0x01;
chr2[i] = bit;
if(i<= 6) signif = signif + bit; //仮数部[6:0]のbit1を集計
}
sprintf(str2,"%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d",
chr2[15], chr2[14], chr2[13],
chr2[12], chr2[11], chr2[10],
chr2[9], chr2[8], chr2[7],
chr2[6], chr2[5], chr2[4],
chr2[3], chr2[2], chr2[1], chr2[0]);
/* 下位16bitを抽出 */
for (i=15; i>=0; i--){
bit=(u_acc.s_acc.s1>>i)&0x01;
chr1[i] = bit;
signif = signif + bit; //仮数部[15:0]のbit1を集計
}
sprintf(str1,"%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d",
chr1[15], chr1[14], chr1[13],
chr1[12], chr1[11], chr1[10],
chr1[9], chr1[8], chr1[7],
chr1[6], chr1[5], chr1[4],
chr1[3], chr1[2], chr1[1], chr1[0]);
/* 2進数表示 */
printf("bin:%s", str2); printf("%s\n", str1);
ret = strtol(str2, &e, 2);
/* 指数部 判定 */
if((ret & 0x7F80) == 0x7F80) //指数部が0xFFか判定
{
/* 仮数部 判定 */
if(signif != 0){
printf("除算結果は非数です。\n");
return 1;
}else{
printf("除算結果は無限大です。\n");
return 0;
}
}else{
printf("除算結果は非数または無限大ではありません。\n");
return 0;
}
}
-
ぽんた
Re: isnan関数の返り値
すみません ちょっとだけコードを見直しました
#include <stdio.h>
#include <stdlib.h>
struct s_tag {
short s1;
short s2;
};
union u_tag {
struct s_tag s_acc;
float f;
} u_acc;
int main(void)
{
int i, bit;
int signif = 0, retval = 0;
int chr1[16], chr2[16];
long int ret;
char str1[17], str2[17], *e;
float num = 0.0, den = 0.0;
u_acc.f = 0.0;
printf("num:"); scanf("%f", &num); //分子
printf("den:"); scanf("%f", &den); //分母
u_acc.f = num / den;
/* 上位16bitを抽出 */
for (i=15; i>=0; i--){
bit=(u_acc.s_acc.s2>>i)&0x01;
chr2[i] = bit;
if(i<= 6) signif = signif + bit; //仮数部[6:0]のbit1を集計
}
sprintf(str2,"%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d",
chr2[15], chr2[14], chr2[13],
chr2[12], chr2[11], chr2[10],
chr2[9], chr2[8], chr2[7],
chr2[6], chr2[5], chr2[4],
chr2[3], chr2[2], chr2[1], chr2[0]);
/* 下位16bitを抽出 */
for (i=15; i>=0; i--){
bit=(u_acc.s_acc.s1>>i)&0x01;
chr1[i] = bit;
signif = signif + bit; //仮数部[15:0]のbit1を集計
}
sprintf(str1,"%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d",
chr1[15], chr1[14], chr1[13],
chr1[12], chr1[11], chr1[10],
chr1[9], chr1[8], chr1[7],
chr1[6], chr1[5], chr1[4],
chr1[3], chr1[2], chr1[1], chr1[0]);
/* 2進数表示 */
printf("bin:%s", str2); printf("%s\n", str1);
/* 上位16bit文字列を2の基数でlong型に変換 */
ret = strtol(str2, &e, 2);
/* 指数部 判定 */
if((ret & 0x7F80) == 0x7F80) //指数部が0xFFか判定
{
/* 仮数部 判定 */
if(signif != 0){
printf("除算結果は非数です。\n");
retval = 1;
}else{
printf("除算結果は無限大です。\n");
retval = 0;
}
}else{
printf("除算結果は非数または無限大ではありません。\n");
retval = 0;
}
return retval;
}