[ part I | part II | grading | submit | extra credit ]
You should create a directory cps100 in which all work for this class will be done (see the initial Unix/Emacs/C++ writeup). Each assignment should be done in its own subdirectory, for this assignment create a directory bigint2. All work for your assignment will then be done in the directory ~/cps100/bigint2. You should change the acl (access control list) on your cps100 directory to give the professor (and TA/UTA) permission to read your files. The command below will give Owen Astrachan (login id 'ola') read permission on the directory cps100.
fs setacl cps100 ola read
Copy the files for this assignment into your bigint2 directory. To do this, cd into the bigint2 directory you created and type
cp ~ola/cps100/bigint/* .
don't forget the final . (dot).
Part II (two parts)
Reimplement Sequence using linked lists.
Re-implement multiplication
Extra Credit
implement Sequence as a templated class
implement subtraction of BigInt values
Subtraction is very tough, you'll need to do a fair amount of work to deal with negative numbers. You can earn partial credit if your code deals with 123 - 45, i.e., subtraction with positive results correctly.
Advice: don't use your linked-list sequence class to test your multiplication code, use the vector sequence class so that you can have high confidence that problems with the program are due to your multiplication code and not to your sequence class.
private:
struct Node
{
int digit;
Node * next;
Node(int val, Node * ptr=0) : digit(val), next(ptr){};
};
int mySize;
Node * myFirst; // first node in linked list
Node * myLast; // last node in linked list
In implementing Sequence you should use a header node. This means that an empty sequence will consist of a single node, pointed to by both myFirst and myLast. Using a header node will simplify writing several member functions. The default constructor can then be implemented as shown below (the -1 could be any number).
Sequence::Sequence()
{
mySize = 0;
myFirst = myLast = new Node(-1); // mark header node
}
}
The Append and Prepend functions should be no more than three to five lines of code each. For example, to append a new digit, a node is created, myLast is updated to point to it, and mySize is incremented (but be careful, there may be special cases that require more than this!). Implementing the destructor, copy constructor, and assignment operator are trickier. For full credit, when implementing the assignment operator you should make use of nodes that already exist (e.g., part of the list being assigned to) rather than creating new nodes unnecessarily.
private:
Sequence & mySequence; // bound to this sequence
Sequence::Node * myCurrent; // internal index of current item
Note that Sequence:: must be used to qualify Node since Node is declared in the private section of Sequence. You should be careful in implementing the function Current since the pointer myCurrent may be NULL. It would be wise to check against this, and if the pointer is NULL, print an error message (to cerr) and abort the program. Be careful when using myCurrent that you remember that a header node is used in implementing the class Sequence
You'll need to alter the Makefile so that it has an entry for testseq.cc. The easiest way to do this is to cut-and-paste one of the entries for expo, fact, or testdiv. Be careful, the character before the $(CC) must be a TAB (when $(CC) occurs after fact:, expo:, testdiv:, etc.). To type a TAB explicitly in emacs you may need to type c-Q TAB (that's control-Q TAB).
A useful first step is to implement a function to multiply a BigInt by an int. To do this properly you will need three functions.
BigInt & operator *= (int num);
BigInt operator * (const BigInt & b, int num)
BigInt operator * (int num, const BigInt & b)
The first of these does most of the work, operator * is
implemented in terms of operator *=.
The code is very similar to the code
for adding two BigInts (see operator +=).
Think about how you would multiply a 50 digit
number by the integer 8 using standard ``grade-school'' methods and
translate this into code. You can then add this operator to the
definitions for the class BigInt in the header file
bigint.h
and implement it in the file bigint.cc.
Your code for multiplying a BigInt by an int only needs to work for digits 0-9. You don't need to make it work for arbitrary integers, although it's not hard to do this. However, if your code only works for digits, you'll need to test this in the function you write and pass the work of digits larger than 10 off to operator *= (BigInt & big). This is to ensure that statements like prod *= 1234 execute correctly. Since 1234 is an int, if your code only handles digits the operator *= (int) function will need to call operator *= (const BigInt &) and pass it BigInt(1234) to return the proper answer.
You'll want to test this code, the factorial function will do this since it computes the factorial of an int not a BigInt. You may want to add some diagnostic output when developing the code to assist in debugging.
| 1 | 2 | 3 | 4 | 5 | 6 | |||
| x | 7 | 8 | 9 | |||||
| ---------------------------------- | ||||||||
| 1 | 1 | 1 | 1 | 1 | 0 | 4 | ||
| 9 | 8 | 7 | 6 | 4 | 8 | 0 | ||
| 8 | 6 | 4 | 1 | 9 | 2 | 0 | 0 | |
| ---------------------------------- | ||||||||
| 9 | 7 | 4 | 0 | 6 | 7 | 8 | 4 | |
Note that each partial product is shifted-left (padded with the appropriate number of zeros). Rather than shift the partial product by adding the appropriate number of zeros, one of the numbers being multiplied can be shifted (of course this is what is really happening in the example above where the top number is multiplied by 9, 80, and 700). This allows the product to be accumulated by summing a sequence of partial products where each partial product involves multiplying by a digit in the range 0-9. In the example above the final product is computed by
(123,456 X 9) + (1,234,560 X 8) + (12,345,600 X 7)
Note that each partial product involves the product of a
BigInt and a digit in the range 0-9. Thus the
partial produces can be
computed using the operator whose
prototype is BigInt & operator *= (int val).
You can use the sequence function Prepend to effectively multiply by 10. You need to use Prepend since the least significant digit is stored first. You will do this when writing the operator whose prototype is below.
BigInt & operator *= (const BigInt &);
Note that because BigInt operator *(const BigInt & a, const BigInt & b) is implemented in terms of *= you'll get good performance ``for free'' for this operator.
For full credit, you should only use Prepend once each time the loop body is executed in the implementation of *=. Read the explanation above carefully to see how this can be done.
| part | points |
|---|---|
| Part I linked-list | |
| testseq.cc | 5 |
| README | 4 |
| sequence.cc | 4 |
| Part II multiplication | |
| *= (int) | 5 |
| *= (const BigInt &) | 5 |
| README | 2 |
To submit use the command
submit100 bigint2 README sequence.h sequence.cc seqiterator.h
seqiterator.cc bigint.h bigint.cc Makefile testseq.cc
If you get a command not found error message, type
~ola/bin/submit100 instead of just submit100
In your README you should include the output of the expo.cc program to demonstrate your successful implementation of the *= operator for BigInt valuess. If you haven't been successful in implementing you can earn substantial credit for indicating where you think the problems lie in your code. You should use expo.cc to calculate 256^256 (or for math aware browsers), submit the result as part of your README file.
To create a templated class, use either the vector implementation or the linked list implementation and change the class declaration and member functions to support sequences of any type. You should include a test program that uses several kinds of sequence. Templates can be difficult to use. The easiest way of testing your template code is to #include both .h and .cc files in testtemplate.cc
// beginning of testtemplate.cc #include "sequence.h" #include "sequence.cc" #include "seqiterator.h" #include "seqiterator.cc"This will ensure that code for each kind of template is instantiated.
Subtraction
Implement subtraction for BigInt values. This is lots of work to get completely correct because of problems like 123 - 123 (what do you do with 000?). You can earn substantial credit for subtraction taht works with results that are positive, e.g., 100 - 7 and full credit if your program deals with negative numbers, e.g, 7 - 100 (then it should deal with negative for addition and multiplication too). Grading
Templates earn 3 A/A+ points, subtraction of positives earns 6 points, and for all values earns 10 points.
Submit
Use
submit100 bigintextra FILES