11

Task

Result

レポート巻末に記載しました。結果は以下のようになりました。

value: 1, enum: 1.0000009999999999177, bin: 0.9999999999, ntn: 1 value: 10, enum: 3.1622800000000004239, bin: 3.16227766, ntn: 3.16227766 value: 100, enum: 10.000099999999999767, bin: 10, ntn: 10 value: 1000, enum: 31.623000000000001108, bin: 31.6227766, ntn: 31.6227766 value: 10000, enum: 100.01000000000000512, bin: 100, ntn: 100 value: 100000, enum: 316.30000000000001137, bin: 316.227766, ntn: 316.227766

Consideration

まず、入力した配列とラムダ関数に対してfor文を実行するeach関数を定義しました。 これによって、コードの可読性が上がったと考えられます。 1~100000までテストしたところ、ntnsqrt関数はほとんど正確な値を計算できました。 bin関数は稀に小さい数を返すことがあることがわかりました。

Ref

#include <stdio.h> #define N 1000000 #define EPSILON 1e-10 void each (int self[], int from=0, auto fun=[]{}) { for (int i = 0; i < from; i++) fun(self[i], i); } double enumsqrt(double x, int i=1) { double dx = x/N, t = dx; for (; ; t=i++*dx) if (t*t-x>0) return t; } double binsqrt(double x) { double a = 0.0, b = x, c = x; for (; ; (c*c-x<0?a:b)=c=a/2+b/2) if (b-a<EPSILON) return a; } double ntnsqrt(double x) { double a = x, b = 2*x; for (; ; a=(b=a)/2+x/2/a) if (b-a<EPSILON) return a; } int main(void) { int cases[] = {1, 10, 100, 1000, 10000, 100000}; each(cases, 6, [](int v, int i){ printf("value: %i, ", v); printf("enum: %.20g, ", enumsqrt(v)); printf("bin: %.10g, ", binsqrt(v)); printf("ntn: %.10g\n", ntnsqrt(v)); }); return 0; }