Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Программирование на C / C++ / Курсовая работа - Сложение чисел в восмеричной системе счисления.doc
Скачиваний:
36
Добавлен:
02.05.2014
Размер:
149.5 Кб
Скачать

Листнинг программы.

//------------------------------------ i8_summator.cpp -------------------------------

// i8_summator.cpp : Defines the entry point for the console application.

//

#include "stdafx.h"

using namespace std;

// Основание системы счисления

#define BASE 8

//длина разрядной сетки целой части

#define MAX_DIGIT_GRID 16

// Максимальное число, которое может кодироваться в 8-ой системе

// с длиной разрядной сетки 16 (по формуле A(q.max)=(q^n)-1 )

#define MAX_NUM (pow(BASE,MAX_DIGIT_GRID)-1) // 07777777777777777

// Число знаков после запятой

#define MAX_FRACTION_PART 8

// @carry: флаг переноса в более старший разряд

// (т.е. число "в уме")

// @summ: результат сложения двух 8-ых чисел,

// величина которых не превышает 7

//

// P.S опытным путем установлено, что "в уме" может быть либо "1",

// либо "0", поэтому используется тип 'bool'

struct i8_data

{

bool carry ;

char summ ;

};

// @carry: флаг переноса

// @digits: массив цифр, который представляет собой восмеричное число

struct i8_data2

{

bool carry ;

deque<char> digits;

};

// i8_data - сложение двух восмеричных чисел

//

// P.S @a и @b должны быть меньше 8.

// В этой функции можно было бы использовать

// таблицу сложения, но поскольку в задании

// такое ограничение отсутствует, используется

// непосредственное вычисление суммы.

// Прим.: если a=5,b=7, то d.summ=4 ,d.carry=true;(07+05=014)

// если a=4,b=2, то d.summ=6 ,d.carry=false;(04+02=06)

i8_data add_c(char a,char b)

{

i8_data d;

if ( a + b > BASE - 1 )

{

d.summ = a + b - BASE ;

d.carry = true ;

}

else

{

d.summ = a + b ;

d.carry = false ;

}

return d;

}

// add_nc - сложение двух восмеричных чисел

// (аналогична add_c, но с небольшой разницей)

//

// P.S результат функции может быть больше 7

// Прим.: если a=7,b=7, то функция вернет 16 ;(07+07=16)

char add_nc(char a,char b)

{

i8_data d=add_c(a,b);

d.summ += d.carry * 10;

return d.summ;

}

// CalcSum - вычисление суммы двух положительных восмеричных чисел

// @first: первое восмеричное число

// @second: второе восмеричное число

// @carry: флаг, символизирующий необходимость добавления

// к указанным числам единицы

//

// P.S @first и @second должны иметь одинаковое количество элементов

i8_data2 CalcSum(const deque<char> &first,const deque<char> &second,bool carry=false)

{

bool carry_flag=carry;

i8_data2 d ;

// поразрядно вычисляем сумму

// Напр. first={3,6,4}, second={2,5,7}

// после цикла: d.digits={5,11,13}

for(int i=first.size()-1 ;i>= 0 ;i--)

{

d.digits.push_front(add_nc(first[i],second[i]));

}

for(int i=d.digits.size()-1; i>= 0 ;i--)

{

if(d.digits[i] < BASE)

{

if(!carry_flag) // если в "уме" 0

continue;

i8_data dt=add_c(d.digits[i],1);

d.digits[i]= dt.summ;

carry_flag = dt.carry;

continue;

}

// в этой ветке: 010 < d.digits[i] < 016

// Напр.: если d.digits[i]==014,и 1 в уме(carry=true), то

// d.digits[i]=5,и единица(из 015) в "уме"

d.digits[i]= d.digits[i] - 10 + carry_flag;

carry_flag = true;

}

d.carry = carry_flag;

return d;

}

// i10_to_i8_fraction - перевод дробной части 10-го числа

// в дробную часть 8-го

// @val: число меньшее 1

deque<char> i10_to_i8_fraction(double val)

{

deque<char> data;

int zero_count=0;

// нормализация ( т.е перед циклом напр.: val = 0.00045,

// после: val = 0.45,zero_count = 3

while ( true )

{

if (val * 10 > 1 || val == 0x00)

break;

val *= 10;

zero_count++;

}

for(int i=0;i<MAX_FRACTION_PART - zero_count ;i++)

{

double xxx = val * BASE ;

char x = static_cast<char>(xxx);

if (x == 0)

break;

data.push_back(static_cast<char>(xxx));

val = xxx - static_cast<__int64>(xxx);

}

if(zero_count > 0)

data.insert(data.begin(),zero_count ,0x00);

if(data.size() != BASE)

data.insert(data.end(),MAX_FRACTION_PART - data.size(),0x00);

return data;

}

// MK_print - вывод массива на стандартный поток вывода

// @val: массив символов

void MK_print(const deque<char> &val,const char *prefix = "")

{

cout << prefix;

if(val.size()==0)

cout << '0';

for(unsigned i=0;i<val.size();i++)

{

// элементы массива @val находятся в виде:

// 0x01,0x02,...,0x07 поэтому необходимо прибавить 0x30,

// чтобы на экран вывелись читабельные символы(т.к. напр. 0x36=='6')

cout << static_cast<char>(val[i] + 0x30);

}

}

// i10_to_i8 - преобразование 10-го числа в 8-е

// @val: целое число

//

// Возвращаемое значение - 8-е число в виде массива чисел

deque<char> i10_to_i8(__int64 val)

{

deque<char> d;

while(val >= BASE )

{

d.push_front(static_cast<char>(val % BASE) );

val /= BASE;

};

if (val < BASE && val > 0)

d.push_front(static_cast<char>(val % BASE) );

return d;

}

// i8_to_i10_and_print - перевод челой и дробной частей

// восмеричного числа в соотв. части

// десятичного и вывод результатов в консоль.

// @val: целая часть восмеричного числа.

// @fract_part: дробная часть восмеричного числа.

void i8_to_i10_and_print(const deque<char> &val,const deque<char> &fract_part)

{

__int64 result = 0;

for(int i=0,pos=val.size()-1;i<val.size();i++,pos--)

{

result += val[i] * pow(BASE,pos);

}

// переводим дробную часть 8-го числа в 10-ю

double d = 0;

for(int i=-1,pos=0;pos < fract_part.size();i--,pos++)

{

d += fract_part[pos] * pow(BASE,i);

}

cout << "The Sum is(oct+oct=oct->dec) : "<< result << '.';

// Вывод дробной части числа (выводятся 8 знаков после запятой)

for(int i=0;i<MAX_FRACTION_PART;i++)

{

d *=10;

cout << (int)d;

d-=static_cast<__int64>(d);

}

cout << endl;

}

// проверка корректности введенного числа

bool is_good_value(double d)

{

if(d > MAX_NUM || d < 0)

{

cout << "ERROR: number out of range..."<<endl;

return false;

}

return true;

}

int main(int argc, char* argv[])

{

double a,b;

cout << "Enter first number : ";

cin >> a;

if(!is_good_value(a))

return 1;

cout << "Enter second number : ";

cin >> b;

if(!is_good_value(b))

return 1;

// переводим целую часть введеных 10-ых чисел в соотв. 8-ые части.

deque<char> first = i10_to_i8(static_cast<__int64>(a));

deque<char> second = i10_to_i8(static_cast<__int64>(b));

// "a - static_cast<__int64>(a)" - таким образом получаем дробную часть числа

// далее переводим эту дробную 10-ю часть в 8-ую.

deque<char> first_frn = i10_to_i8_fraction(a - static_cast<__int64>(a));

deque<char> second_frn = i10_to_i8_fraction(b - static_cast<__int64>(b));

// если напр. first="1234567", second="52",

// то после этого блока second = "0000052"

// это необходимо для корректной работы функции CalcSum

if(first.size() > second.size())

second.insert(second.begin(),first.size()-second.size(),0x00);

else if (second.size()-first.size())

first.insert(first.begin(),second.size()-first.size(),0x00);

MK_print(first,"First number(octal) is : ");

cout << '.';

MK_print(first_frn);

cout <<endl;

MK_print(second,"Second number(octal) is : ");

cout << '.';

MK_print(second_frn);

cout <<endl;

// складываем дробные части

// если результат сложения >= 1, dd1.carry устанавливается в "true"

i8_data2 dd1 = CalcSum(first_frn,second_frn);

i8_data2 result = CalcSum(first,second,dd1.carry);

if (result.carry)

result.digits.push_front(0x01);

// Если произошло переполнение разрядной сетки

// выдаём соотв. сообщение.

if(result.digits.size() > MAX_DIGIT_GRID)

{

cout << "ERROR: overflow occured while adding two entered digits!!!"<<endl;

return 1;

}

MK_print(result.digits,"The Sum is(octal) : ");

cout << '.';

MK_print(dd1.digits);

cout <<endl;

// переводим полученное 8-е число в 10-е и выводим 10-е число на консоль.

i8_to_i10_and_print(result.digits,dd1.digits);

// выводим число,которое должно было бы получится

// при непосредственном сложении двух введенных чисел.

cout << "The Sum is(dec+dec=dec) : "<<a+b<<endl;

return 0;

}

//------------------------------ i8_summator.cpp ------------------------------

//------------------------------ stdafx.cpp ------------------------------------

#include "stdafx.h"

//------------------------------ stdafx.cpp ------------------------------------

//------------------------------ stdafx.h --------------------------------------

#pragma once

#define WIN32_LEAN_AND_MEAN

#include <math.h>

#include <deque>

#include <iostream>

//------------------------------ stdafx.h --------------------------------------

13