2014年4月18日金曜日

開発環境

C++実践プログラミング (スティーブ オウアルライン (著)、Steve Oualline (原著)、Steve Oualline(原著)、望月 康司(翻訳)、クイープ(翻訳) 、オライリー・ジャパン)のⅣ部(高度なプログラミング概念)の19章(浮動小数点)、19.11(プログラミング実習)、実習 19-1.を解いてみる。

その他参考書籍

実習 19-1.

コード(BBEdit, Emacs)

my_float.h

#ifndef __my_float_h__
#define __my_float_h__
#include <iostream>

namespace my_float {
  class my_float {
  private:
    int n;
    int e;
  public:
    my_float () {
      n = 0;
      e = 0;
    }
    my_float(int n1, int e1 ) {
      n = n1;
      e = e1;
    }

    /* my_float(const my_float& old_my_float); */
    /* ~my_float(); */
    /* my_float operator = (const my_float& old_my_float); */
    friend my_float operator + (const my_float& op1, const my_float& op2);
    friend my_float operator - (const my_float& op1, const my_float& op2);
    friend my_float operator * (const my_float& op1, const my_float& op2);
    friend my_float operator / (const my_float& op1, const my_float& op2);
    friend std::ostream& operator << (std::ostream& out_file,
                                      const my_float& f);
    friend std::istream& operator >> (std::istream& in_file, my_float& f);
  };

  inline my_float operator + (const my_float& op1, const my_float& op2)
  {
    int op1_n = op1.n;
    int op1_e = op1.e;
    int op2_n = op2.n;
    int op2_e = op2.e;
    int n;
    int e;
    int s;
    int t;

    if (op1_e < op2_e) {
      e = op2_e;
      for (; op1_e != op2_e; ++op1_e)
        op1_n /= 10;
    }
    else {
      e = op1_e;
      for (; op1_e != op2_e; ++op2_e)
        op2_n /= 10;
    }
    
    n = op1_n + op2_n;

    if (n < 0) {
      s = -1;
      n *= -1;
    } else
      s = 1;
    for (; n >= 100000; ++e)
      n /= 10;

    if (n == 0)
      return my_float(0, 0);
    for (; n < 10000; --e)
      n *= 10;
    t = n % 10;
    n -= t;
    n += t >= 5 ? 10 : 0;
    return my_float(s * n, e);
  }

  inline my_float operator - (const my_float& op1, const my_float& op2)
  {
    return op1 + my_float(-1 * op2.n, op2.e);
  }

  inline my_float operator * (const my_float& op1, const my_float& op2)
  {
    int n = op1.n * op2.n;
    int e = op1.e + op2.e;
    int s;
    int t;

    if (n < 0) {
      s = -1;
      n *= -1;
    } else
      s = 1;
    if (n == 0)
      return my_float(0, 0);
    for (; n >= 100000; ++e)
      n /= 10;

    if (n == 0)
      return my_float(0, 0);
    for (; n < 10000; --e)
      n *= 10;
    t = n % 10;
    n -= t;
    n += t >= 5 ? 10 : 0;
    return my_float(s * n, e);
  }

  inline my_float operator / (const my_float& op1, const my_float& op2)
  {
    int n;
    int e;
    int s;
    int t;
    float f;

    if (op1.n == 0)
      return my_float(0, 0);
    if (op2.n == 0)
      return my_float(-10000, 0);
    
    f = (float) op1.n / op2.n;
    n = (int) f * 10000;

    if (n == 0)
      return my_float(0, 0);
    if (n < 0) {
      s = -1;
      n *= -1;
    } else
      s = 1;
    e = op1.e - op1.e;
    for (; n >= 100000; ++e)
      n /= 10;
    if (n == 0)
      return my_float(0, 0);
    for (; n < 10000; --e)
      n *= 10;
    t = n % 10;
    n -= t;
    n += t >= 5 ? 10 : 0;
    return my_float(s * n, e);
  }

  extern std::ostream& operator << (std::ostream& out_file, const my_float& f);
  extern std::istream& operator >> (std::istream& in_file, my_float& f);
}
#endif  /*__my_float_h__ */

my_float.cpp

#include <iostream>
#include "my_float.h"

namespace my_float {
  std::ostream& operator << (std::ostream& out_file, const my_float& f)
  {
    int n;
    int e;
    int f1;
    int f2;
    int f3;
    int f4;
    char s1;
    char s2;

    if (f.n >= 0) {
      s1 = '+';
      n = f.n;
    }
    else {
      s1 = '-';
      n = -1 * f.n;
    }

    if (f.e >= 0) {
      s2 = '+';
      e = f.e;
    }
    else {
      s2 = '-';
      e = -1 * f.e;
    }
    f1 = n / 10000;
    n %= 10000;
    f2 = n / 1000;
    n %= 1000;
    f3 = n / 100;
    n %= 100;
    f4 = n / 10;
    n %= 10;
    f4 += n >= 5 ? 1 : 0;
    out_file << s1 << f1 << '.' << f2 << f3 << f4 << 'E' << s2 << e;
    return (out_file);
  }
  
  std::istream& operator >> (std::istream& in_file, my_float& f)
  {
    char s1;
    int f1;
    int f2;
    int f3;
    int f4;
    char s2;
    char ch;

    f.n = 0;
    f.e = 0;
    
    std::istream::sentry the_sentry(in_file, true);
    if (the_sentry) {
      if (in_file.fail()) return (in_file);

      in_file >> s1;
      if (in_file.fail()) return (in_file);
      if (s1 != '+' && s1 != '-') {
        in_file.setstate(std::ios::failbit);
        return (in_file);
      }
   
      in_file >> ch;
      if (in_file.fail()) return (in_file);
      if (ch < '0' && ch > '9') {
        in_file.setstate(std::ios::failbit);
        return (in_file);
      }      
      f1 = static_cast<int>(ch - '0');

      in_file >> ch;
      if (in_file.fail()) return (in_file);
      if (ch != '.') {
        in_file.setstate(std::ios::failbit);
        return (in_file);
      }

      in_file >> ch;
      if (in_file.fail()) return (in_file);
      if (ch < '0' && ch > '9') {
        in_file.setstate(std::ios::failbit);
        return (in_file);
      }
      f2 = static_cast<int>(ch - '0');

      in_file >> ch;
      if (in_file.fail()) return (in_file);
      if (ch < '0' && ch > '9') {
        in_file.setstate(std::ios::failbit);
        return (in_file);
      }
      f3 = static_cast<int>(ch - '0');
      
      in_file >> ch;
      if (in_file.fail()) return (in_file);
      if (ch < '0' && ch > '9') {
        in_file.setstate(std::ios::failbit);
        return (in_file);
      }
      f4 = static_cast<int>(ch - '0');

      in_file >> ch;
      if (in_file.fail()) return (in_file);
      if (ch != 'E') {
        in_file.setstate(std::ios::failbit);
        return (in_file);
      }

      in_file >> s2;
      if (in_file.fail()) return (in_file);
      if (s2 != '+' && s2 != '-') {
        in_file.setstate(std::ios::failbit);
        return (in_file);
      }

      in_file >> ch;
      if (in_file.fail()) return (in_file);
      if (ch < '0' && ch > '9') {
        in_file.setstate(std::ios::failbit);
        return (in_file);
      }
      f.e = static_cast<int>(ch - '0');

      f.n = f1 * 10000 + f2 * 1000 + f3 * 100 + f4 * 10;
      f.n *= s1 == '+' ? 1 : -1;
      f.e *= s2 == '+' ? 1 : -1;
    }
    else
      in_file.setstate(std::ios::failbit);

    return (in_file);
  }
}

test_my_float.cpp

#include <iostream>

#include "my_float.h"

int main(int argc, char *argv[])
{
  my_float::my_float f0;
  my_float::my_float f1(-54325,2);
  my_float::my_float f2(33330, -1);
  my_float::my_float f3;

  std::cout << f0 << "(+0.000E+0)" << std::endl;
  std::cout << f1 << "(-5.433E+2)" << std::endl;
  std::cout << f2 << "(3.333E-1)" << std::endl;

  std::cout << "浮動小数点数を入力(±d.dddE±d)>> ";
  std::cin >> f3;
  std::cout << f3 << std::endl;

  std::cout << f0 << " + " << f1 << " = " << f0 + f1 << std::endl;
  std::cout << f1 << " + " << f0 << " = " << f1 + f0 << std::endl;
  std::cout << f1 << " + " << f2 << " = " << f1 + f2 << std::endl;
  std::cout << f2 << " + " << f1 << " = " << f2 + f1 << std::endl;
  std::cout << f2 << " + " << f3 << " = " << f2 + f3 << std::endl;
  std::cout << f3 << " + " << f2 << " = " << f3 + f2 << std::endl;

  std::cout << f0 << " - " << f1 << " = " << f0 - f1 << std::endl;
  std::cout << f1 << " - " << f0 << " = " << f1 - f0 << std::endl;
  std::cout << f1 << " - " << f2 << " = " << f1 - f2 << std::endl;
  std::cout << f2 << " - " << f1 << " = " << f2 - f1 << std::endl;
  std::cout << f2 << " - " << f3 << " = " << f2 - f3 << std::endl;
  std::cout << f3 << " - " << f2 << " = " << f3 - f2 << std::endl;

  std::cout << f0 << " * " << f1 << " = " << f0 * f1 << std::endl;
  std::cout << f1 << " * " << f0 << " = " << f1 * f0 << std::endl;
  std::cout << f1 << " * " << f2 << " = " << f1 * f2 << std::endl;
  std::cout << f2 << " * " << f1 << " = " << f2 * f1 << std::endl;
  std::cout << f2 << " * " << f3 << " = " << f2 * f3 << std::endl;
  std::cout << f3 << " * " << f2 << " = " << f3 * f2 << std::endl;

  std::cout << f0 << " / " << f1 << " = " << f0 / f1 << std::endl;
  std::cout << f1 << " / " << f0 << " = " << f1 / f0 << std::endl;
  std::cout << f1 << " / " << f2 << " = " << f1 / f2 << std::endl;
  std::cout << f2 << " / " << f1 << " = " << f2 / f1 << std::endl;
  std::cout << f2 << " / " << f3 << " = " << f2 / f3 << std::endl;
  std::cout << f3 << " / " << f2 << " = " << f3 / f2 << std::endl;

  return (0);
}

Makefile

CC=g++
CFLAGS=-g -Wall
all: test_my_float

test_my_float: test_my_float.cpp my_float.o
 ${CC} ${CFLAGS} -o test_my_float test_my_float.cpp my_float.o

my_float.o: my_float.cpp my_float.h
 ${CC} -c -o my_float.o my_float.cpp

clean:
 rm test_my_float

入出力結果(Terminal)

$ make && ./test_my_float
g++ -c -o my_float.o my_float.cpp
g++ -g -Wall -o test_my_float test_my_float.cpp my_float.o
+0.000E+0(+0.000E+0)
-5.433E+2(-5.433E+2)
+3.333E-1(3.333E-1)
浮動小数点数を入力(±d.dddE±d)>> +3.333E-1
+3.333E-1
+0.000E+0 + -5.433E+2 = -5.433E+2
-5.433E+2 + +0.000E+0 = -5.433E+2
-5.433E+2 + +3.333E-1 = -5.429E+2
+3.333E-1 + -5.433E+2 = -5.429E+2
+3.333E-1 + +3.333E-1 = +6.666E-1
+3.333E-1 + +3.333E-1 = +6.666E-1
+0.000E+0 - -5.433E+2 = +5.433E+2
-5.433E+2 - +0.000E+0 = -5.433E+2
-5.433E+2 - +3.333E-1 = -5.436E+2
+3.333E-1 - -5.433E+2 = +5.436E+2
+3.333E-1 - +3.333E-1 = +0.000E+0
+3.333E-1 - +3.333E-1 = +0.000E+0
+0.000E+0 * -5.433E+2 = +0.000E+0
-5.433E+2 * +0.000E+0 = +0.000E+0
-5.433E+2 * +3.333E-1 = -1.811E+6
+3.333E-1 * -5.433E+2 = -1.811E+6
+3.333E-1 * +3.333E-1 = +1.111E+3
+3.333E-1 * +3.333E-1 = +1.111E+3
+0.000E+0 / -5.433E+2 = +0.000E+0
-5.433E+2 / +0.000E+0 = -1.000E+0
-5.433E+2 / +3.333E-1 = -1.000E+0
+3.333E-1 / -5.433E+2 = +0.000E+0
+3.333E-1 / +3.333E-1 = +1.000E+0
+3.333E-1 / +3.333E-1 = +1.000E+0
$

0 コメント:

コメントを投稿