HOME»応用情報技術者試験掲示板»令和4年春期午前第1問
投稿する
ありがとうござます。大体納得できました。
離散数学を学ぶ旅に出ます。
令和4年春期午前第1問 [3404]
ももねさん(No.1)
二進数を10進数に直して、エクセルにぶち込んで指数計算を行いましたが、
どの選択肢も桁落ちしませんでした・・・。
なんなんですかこの問題は?
どの選択肢も桁落ちしませんでした・・・。
なんなんですかこの問題は?
2022.04.26 17:20
nsさん(No.2)
★AP ブロンズマイスター
まず、この設問で問われているのは"桁落ち"ではなく"情報落ち"です。
そして、問題の前提として"仮数部が7ビット"となっています。
エクセルが小数値を何ビットで保持しているかは私も把握していませんが、少なくとも仮数部が7ビットということはないでしょう。
一般に32ビット小数なら仮数部は23ビット、64ビット小数なら仮数部は52ビット持つことができます。
そして、問題の前提として"仮数部が7ビット"となっています。
エクセルが小数値を何ビットで保持しているかは私も把握していませんが、少なくとも仮数部が7ビットということはないでしょう。
一般に32ビット小数なら仮数部は23ビット、64ビット小数なら仮数部は52ビット持つことができます。
2022.04.26 17:41
あああさん(No.3)
アウの最終的な答えは32.25、イエは32.125になります。
細かい説明は省きますが、32.125の表現には仮数部が7ビットでは足りません。(8ビット必要)
なので、アウの2択となります。
試験が終わった後にC言語で確認したときのコードを貼っておきますね。
このコードを実行すると「a2:0x1,5 u2:0x0,5」と表示されます。
期待値はどちらも0x1,5になるべきなので、ウで情報落ちが発生していることが分かります。
なお、即興で作ったのでソースコードは読めたものではないですが、
このコードが何をしているのかが分かると、浮動小数点の理解が深まると思います。
void before_align(int * a_sig, int * a_exp, int * b_sig, int * b_exp) {
while(*a_exp != *b_exp) {
if(*a_exp > *b_exp) {
(*b_exp)++;
(*b_sig) >>= 1;
} else {
(*a_exp)++;
(*a_sig) >>= 1;
}
}
}
void after_align(int * sig, int * expo) {
while((*sig & 0xffffff00) != 0) {
(*sig) >>= 1;
(*expo)++;
}
while((*sig & 0xffffff80) == 0) {
(*sig) <<= 1;
(*expo)--;
}
}
void plus(int a_sig, int a_exp, int b_sig, int b_exp, int * result_sig, int * result_exp) {
a_sig += 0b10000000;
b_sig += 0b10000000;
before_align(&a_sig, &a_exp, &b_sig, &b_exp);
int temp_sig = a_sig + b_sig;
int temp_exp = a_exp;
after_align(&temp_sig, &temp_exp);
*result_sig = temp_sig & 0xffffff7f;
*result_exp = temp_exp;
}
int main(void) {
// ア
{
int ans_sig = 0, ans_exp = 0;
plus(0b1000000, -3, 0b0000000, -4, &ans_sig, &ans_exp);
printf("a1:0x%x,%d\n", ans_sig, ans_exp);
plus(ans_sig, ans_exp, 0b0000000, 5, &ans_sig, &ans_exp);
printf("a2:0x%x,%d\n", ans_sig, ans_exp);
}
// ウ
{
int ans_sig = 0, ans_exp = 0;
plus(0b0000000, 5, 0b1000000, -3, &ans_sig, &ans_exp);
printf("u1:0x%x,%d\n", ans_sig, ans_exp);
plus(ans_sig, ans_exp, 0b0000000, -4, &ans_sig, &ans_exp);
printf("u2:0x%x,%d\n", ans_sig, ans_exp);
}
}
細かい説明は省きますが、32.125の表現には仮数部が7ビットでは足りません。(8ビット必要)
なので、アウの2択となります。
試験が終わった後にC言語で確認したときのコードを貼っておきますね。
このコードを実行すると「a2:0x1,5 u2:0x0,5」と表示されます。
期待値はどちらも0x1,5になるべきなので、ウで情報落ちが発生していることが分かります。
なお、即興で作ったのでソースコードは読めたものではないですが、
このコードが何をしているのかが分かると、浮動小数点の理解が深まると思います。
#include <stdio.h>
void before_align(int * a_sig, int * a_exp, int * b_sig, int * b_exp) {
while(*a_exp != *b_exp) {
if(*a_exp > *b_exp) {
(*b_exp)++;
(*b_sig) >>= 1;
} else {
(*a_exp)++;
(*a_sig) >>= 1;
}
}
}
void after_align(int * sig, int * expo) {
while((*sig & 0xffffff00) != 0) {
(*sig) >>= 1;
(*expo)++;
}
while((*sig & 0xffffff80) == 0) {
(*sig) <<= 1;
(*expo)--;
}
}
void plus(int a_sig, int a_exp, int b_sig, int b_exp, int * result_sig, int * result_exp) {
a_sig += 0b10000000;
b_sig += 0b10000000;
before_align(&a_sig, &a_exp, &b_sig, &b_exp);
int temp_sig = a_sig + b_sig;
int temp_exp = a_exp;
after_align(&temp_sig, &temp_exp);
*result_sig = temp_sig & 0xffffff7f;
*result_exp = temp_exp;
}
int main(void) {
// ア
{
int ans_sig = 0, ans_exp = 0;
plus(0b1000000, -3, 0b0000000, -4, &ans_sig, &ans_exp);
printf("a1:0x%x,%d\n", ans_sig, ans_exp);
plus(ans_sig, ans_exp, 0b0000000, 5, &ans_sig, &ans_exp);
printf("a2:0x%x,%d\n", ans_sig, ans_exp);
}
// ウ
{
int ans_sig = 0, ans_exp = 0;
plus(0b0000000, 5, 0b1000000, -3, &ans_sig, &ans_exp);
printf("u1:0x%x,%d\n", ans_sig, ans_exp);
plus(ans_sig, ans_exp, 0b0000000, -4, &ans_sig, &ans_exp);
printf("u2:0x%x,%d\n", ans_sig, ans_exp);
}
}
2022.04.27 10:42
GinSanaさん(No.4)
★AP プラチナマイスター
この投稿は投稿者により削除されました。(2022.04.27 11:18)
2022.04.27 11:18
GinSanaさん(No.5)
★AP プラチナマイスター
補足ですが、ExcelはIEEE 754に従うように設計されていて、2.8×10^-17以下は切り捨てられると思ってください。
2022.04.27 11:18
ももねさん(No.6)
>みなさま
ありがとうござます。大体納得できました。
離散数学を学ぶ旅に出ます。
2022.04.27 13:31