近似と精確——《狂人C》習題解答15(第三章習題5)
3946 ワード
以前、ある農夫が死んでから15頭の牛を残していた.遺書には、「妻は牛の半分を全部分けて半分、長男は牛の半分を分けて半分、次男は牛の半分を分けて半分、次男は牛の半分を分けて半分、長女は最後の残りを分けて」とある.プログラミングで長女に牛を何頭かもらいました.
これは簡単な小学校の算数の問題です.15頭の牛の半分は7と1/2で、半分を加えると8になります.これは妻が得たものです.残り7頭7頭の牛の半分は3と1/2で、さらに半分を加えて4になるのが長男の所得です.残り3頭の3頭の牛の半分は1また1/2で、さらに半分を加えると2になります.これは次男の所得です.残り1頭のため長女は1頭を得た.
しかし、次のようなコードを書くと、最大60点しか得られません.
出力:長女は1億2000万頭の牛を手に入れた
第一に、この結果は長女が得た牛の数が約1頭に等しいことを示しているだけだからだ.第二に、コードは実際に前の算術演算プロセスを実現していない.例えばqizi=shengyu*FENPEI_BL + EWAI_TJ ;表す意味は、前の算術演算中の正確な演算ではなく、いくつかの近似値の近似演算にすぎない.その本質と普遍的な状況について言えば、実浮動小数点タイプのデータは実数に対する近似表現にすぎないため、これは実浮動小数点タイプの演算も近似演算にすぎない.ただし,本問題では近似の精度が高く,計算結果は正確な結果と一致しているだけである.プログラムを筆算プロセスの正確なシミュレーションと見なせば,前のコードが要求に合致していないことは明らかである.コンピュータでは、整数タイプのみが整数集合のサブセットの近似表現です.したがって,筆算プロセスを正確にシミュレートするには整数タイプしか使用できない.しかし、筆算の過程は点数に及んだ.数学では、点数も正確な表現であるが、C言語ではそれに対応する「点数タイプ」はない.対応するデータ型がなければどうしますか?答えは簡単です.このタイプがなければ、このデータ型を作成します.創造性のために広大な発揮空間を提供したのはC言語の特徴と魅力であり、プログラミングの楽しみの一つでもある.分数は分子、分母の2つの部分からなり、分子、分母はいずれも整数であるため、2つの整数タイプのデータで分数を表すことができる.このようなデータに対して、C言語は直接的な演算を提供していないが、このような「点数」の演算には、自分でC言語で提供された演算シミュレーションが必要である.例えば、a/b+c/dを計算すると、1回の「+」演算では完了せず、和の分子「b*c+d*c」と和の分母「a*c」を2回に分けて計算するしかない.この方法で得られたコードは
出力:長女は1又0/16384頭の牛をもらいました
これは正確な結果です.【注:制御文と関数理論を学習した後、後のコードをさらに改善することができます.】
これは簡単な小学校の算数の問題です.15頭の牛の半分は7と1/2で、半分を加えると8になります.これは妻が得たものです.残り7頭7頭の牛の半分は3と1/2で、さらに半分を加えて4になるのが長男の所得です.残り3頭の3頭の牛の半分は1また1/2で、さらに半分を加えると2になります.これは次男の所得です.残り1頭のため長女は1頭を得た.
しかし、次のようなコードを書くと、最大60点しか得られません.
#include <stdio.h>
#include <stdlib.h>
#define ZONGSHU 15. // : 15
#define FENPEI_BL .5 // :
#define EWAI_TJ .5 // :
int main( void )
{
double qizi , zhangzi , cizi , zhangnv ; // 、 、 、
double shengyu = ZONGSHU ; //
qizi = shengyu * FENPEI_BL + EWAI_TJ ; //
shengyu -= qizi ; //
zhangzi = shengyu * FENPEI_BL + EWAI_TJ ; //
shengyu -= zhangzi ; //
cizi = shengyu * FENPEI_BL + EWAI_TJ ; //
shengyu -= cizi ; //
zhangnv = shengyu ; // :
printf(" %f
" , zhangnv ) ;
system("PAUSE");
return 0;
}
出力:長女は1億2000万頭の牛を手に入れた
第一に、この結果は長女が得た牛の数が約1頭に等しいことを示しているだけだからだ.第二に、コードは実際に前の算術演算プロセスを実現していない.例えばqizi=shengyu*FENPEI_BL + EWAI_TJ ;表す意味は、前の算術演算中の正確な演算ではなく、いくつかの近似値の近似演算にすぎない.その本質と普遍的な状況について言えば、実浮動小数点タイプのデータは実数に対する近似表現にすぎないため、これは実浮動小数点タイプの演算も近似演算にすぎない.ただし,本問題では近似の精度が高く,計算結果は正確な結果と一致しているだけである.プログラムを筆算プロセスの正確なシミュレーションと見なせば,前のコードが要求に合致していないことは明らかである.コンピュータでは、整数タイプのみが整数集合のサブセットの近似表現です.したがって,筆算プロセスを正確にシミュレートするには整数タイプしか使用できない.しかし、筆算の過程は点数に及んだ.数学では、点数も正確な表現であるが、C言語ではそれに対応する「点数タイプ」はない.対応するデータ型がなければどうしますか?答えは簡単です.このタイプがなければ、このデータ型を作成します.創造性のために広大な発揮空間を提供したのはC言語の特徴と魅力であり、プログラミングの楽しみの一つでもある.分数は分子、分母の2つの部分からなり、分子、分母はいずれも整数であるため、2つの整数タイプのデータで分数を表すことができる.このようなデータに対して、C言語は直接的な演算を提供していないが、このような「点数」の演算には、自分でC言語で提供された演算シミュレーションが必要である.例えば、a/b+c/dを計算すると、1回の「+」演算では完了せず、和の分子「b*c+d*c」と和の分母「a*c」を2回に分けて計算するしかない.この方法で得られたコードは
#include <stdio.h>
#include <stdlib.h>
#define ZONGSHU_FZ 15 //
#define ZONGSHU_FM 1 //
#define FENPEI_BL_FZ 1 //
#define FENPEI_BL_FM 2 //
#define EWAI_TJ_FZ 1 //
#define EWAI_TJ_FM 2 //
int main( void )
{
int qizi_fm , qizi_fz , //
zhangzi_fm , zhangzi_fz , //
cizi_fm , cizi_fz , //
zhangnv_fm , zhangnv_fz ; //
int shengyu_fm = ZONGSHU_FM , //
shengyu_fz = ZONGSHU_FZ ; //
qizi_fz = shengyu_fz * EWAI_TJ_FM //
+ shengyu_fm * FENPEI_BL_FM * FENPEI_BL_FZ;
qizi_fm = shengyu_fm * FENPEI_BL_FM * EWAI_TJ_FM ;
shengyu_fz = shengyu_fz * qizi_fm - qizi_fz * shengyu_fm ; //
shengyu_fm *= qizi_fm ;
zhangzi_fz = shengyu_fz * EWAI_TJ_FM //
+ shengyu_fm * FENPEI_BL_FM * FENPEI_BL_FZ;
zhangzi_fm = shengyu_fm * FENPEI_BL_FM * EWAI_TJ_FM ;
shengyu_fz = shengyu_fz * zhangzi_fm - zhangzi_fz * shengyu_fm ; //
shengyu_fm *= zhangzi_fm ;
cizi_fz = shengyu_fz * EWAI_TJ_FM //
+ shengyu_fm * FENPEI_BL_FM * FENPEI_BL_FZ;
cizi_fm = shengyu_fm * FENPEI_BL_FM * EWAI_TJ_FM ;
shengyu_fz = shengyu_fz * cizi_fm - cizi_fz * shengyu_fm ; //
shengyu_fm *= cizi_fm ;
zhangnv_fz = shengyu_fz ; //
zhangnv_fm = shengyu_fm ;
printf(" %d %d/%d
" ,
shengyu_fz/shengyu_fm , shengyu_fz % shengyu_fm , shengyu_fm ) ;
system("PAUSE");
return 0;
}
出力:長女は1又0/16384頭の牛をもらいました
これは正確な結果です.【注:制御文と関数理論を学習した後、後のコードをさらに改善することができます.】