В настоящее время я выполняю школьное задание (извините, что мой вопрос касается моего задания, но я не спрашиваю об алгоритмах, используемых в кодах). Сейчас я занимаюсь арифметической частью, сложением и вычитанием. Поскольку есть только два оператора, есть 8 комбинаций операций. В моей программе я могу выполнить эти четыре случая:
(+a)+(+b)
(-a)+(-b)
(-a)-(+b)
(+a)-(-b)
Тем не менее, я не могу понять, как сделать другие четыре случая,
То есть
(+a)+(-b)
(-a)+(+b)
(-a)-(-b)
(+a)-(+b)
Я искренне надеюсь, что вы, ребята, сможете дать предложения и советы о том, как справиться с этими четырьмя случаями.
Вот мой код:
linkedListType.h:
Это обычный заголовочный файл связанного списка, поэтому я не публикую здесь весь код.
bigInteger.h:
Функции в этом довольно длинные. Поэтому я пропустил их публикацию.
#ifndef BIG_INTEGER_H
#define BIG_INTEGER_H
#include <stack>
#include <iostream>
#include "linkedListType.h"
using namespace std;
class bigInteger
{
private:
int sign; // set 0 for positive, 1 for negative
linkedListType<int> digits; // internal linked-list for storing digits in reverse order
public:
bigInteger(); // default constructor
bigInteger(const bigInteger& other); // copy constructor
// Overload constructor
// Use an numerical string to construct this bigInteger
// For negative number, the first char in the string is '-'
// e.g. "-12345"bigInteger(const string& number);
// overload the assignment operator
const bigInteger& operator= (const bigInteger& other);
// Return a new bigInteger that is equal to *this + other
// The contents of this and other should not be modified
bigInteger& operator+ (bigInteger& other);
// Return a new bigInteger that is equal to *this - other
// The contents of this and other should not be modified
bigInteger& operator- (bigInteger& other);
// Print a big integer
// Since the digits are stored in reverse order in the internal
// list, you should print in reverse order
// Print "undefined" if the digits list is empty
friend ostream& operator<<(ostream& os, bigInteger& n);
};
хорошо, все комментарии обрабатывают вещи перегрузки оператора, но я подозреваю, что OP — о том, как вычислить все комбинации знаков операндов для сложения и вычитания.
дополнение двух
ну большинство HW реализации целых ALU использовать два дополнения для представления чисел со знаком. Это означает:
-X = (X^0xFFFFFFFF)+1; // 32 bit example
это отрицательное значение, полученное путем инвертирования всех битов и увеличения результата. Таким образом, вы можете использовать архитектуру с одним сумматором для всех комбинаций добавления / подписи и знака, пока бит знака еще MSB. Эта кодировка обрабатывает подписанные и неподписанные операции одинаково, поэтому для сложения у вас нет никаких проблем (ничего не нужно делать, просто добавьте), а для вычитания просто инвертируйте знак второго операнда и добавьте.
Реализация C ++ выглядит так:
bool bigInteger::sign() { return MSB_of_this; }
bigInteger bigInteger::operator+ () { bigInteger z=*this; return z; }
bigInteger bigInteger::operator- () { bigInteger z=*this; /* here negate all bits and increment z*/ return z' |z; }
bigInteger bigInteger::operator+ (bigInteger& y)
{
bigInteger z;
// here do z = *this + y as if all operands were positive
return z;
}
bigInteger bigInteger::operator- (bigInteger& y0)
{
bigInteger z;
y=-y0; // invert sign in temp variable to avoid changing input operand value !!!
// here do z = *this + y as if all operands were positive
return z;
}
обратите внимание, что я не изменяю входной операнд, и все возвращаемые значения являются отдельной переменной (не использую это даже для унарного +). Это связано с цепочкой операндов. Некоторым компиляторам трудно объединить более 3 операторов в одну строку, если они не закодированы таким образом, что означает, что вы не можете компилировать такие строки, как
c=a+b-c*a*b/(s-d)+(23*q);
вместо этого вам придется разбить его на более простые термины …
В случае, если вы не используете два дополнения
Затем вы должны обработать знаки входного операнда. Наиболее распространенным случаем является то, что у вас есть флаг знака как отдельная переменная, а не внутри битов числа. В этом случае вам понадобятся некоторые функции, которые вообще не учитывают знак
bigInteger uadd(bigInteger &a,bigInteger &b); //=|a|+|b|
bigInteger usub(bigInteger &a,bigInteger &b); //=|a|-|b| but operands must be: |a|>|b|
bool ugeq(bigInteger &a,bigInteger &b); //=|a|>=|b| Unsigned Greater or EQual
из этого легко
прибавление
Substraction
Так было бы что-то вроде этого:
bigInteger bigInteger::operator+ (bigInteger& y)
{
bigInteger z;
bool sx,sy;
sx=sign();
sy=y.sign();
if (sx==sy) z=uadd(*this,y); // same signs is add
else // not then first operand for (a-b) is the positive one
{
if (sx) return y-(*this);
else return (*this)-y;
}
// here set the sign to the same as operands
z.set_sign(sx);
return z;
}
так как это задание, я оставлю -
оператор без кода.
Это будет очень похоже на +
оператор, но вам нужно отсортировать входные операнды по абсолютному размеру (используя ugeq
) и установите результат sign
от абс больше. если вы поменяли местами операнды, инвертируйте знак результата. Вычитать только, если операнды на стенде совпадают с тем же знаком (a+b)
…
Надеюсь, это поможет немного