C++ Add and Subtracting 100 digits numbers - c++

So what it's supposed to do is be able to take in a const char* str change it to an int then have it be converted back into a string for the output. But it is also supposed to be able to add and subtract these together. I'm passing my first two tests but something is going on with my addition, its giving me a negative number close to the answer but not the right one. Shortened it up a bit.
//For testing
int main()
{
BigInt result;
BigInt num1("999");
BigInt num2("4873");
BigInt num3("-739");
checkTest("Test 1", "999", num1.convertToString());
checkTest("Test 2", "-739", num3.convertToString());
result = num3.add(num4);
checkTest("Test 3", "-10610", result.convertToString());
return 0;
}
Here is where I'm having trouble
#include <iostream>
using namespace std;
class BigInt
{
public:
//An empty constructor, the {} is an empty body
BigInt() {}
BigInt(const char*);
BigInt add(const BigInt&);
BigInt operator+(const BigInt&);
BigInt subtract(const BigInt&);
BigInt operator-(const BigInt&);
string convertToString();
private:
static const int NUM_DIGITS = 100;
int numArr[NUM_DIGITS + 1];
void tensComplement();
};
BigInt::BigInt(const char* str) {
// TODO: CONVERT C-STRING TO BIGINT
int len = strlen(str) - 1;
int zero = NUM_DIGITS - 1;
for (int i = 0; i < NUM_DIGITS; i++){
numArr[i] = 48;
}
for (int i = len; i >= 0; i--){
numArr[zero] = str[i];
zero--;
}
}
BigInt BigInt::add(const BigInt& rightOperand) {
BigInt objToReturn("0");
// TODO: ADD LOGIC HERE
int carry = 0;
for (int i = 100; i > 0; i--){
int left = this->numArr[i] - 48;
int right = rightOperand.numArr[i] - 48;
int total = left + right;
total += carry;
if (total > 9){
carry = 1;
}else{
carry = 0;
}
total = total % 10;
objToReturn.numArr[i] = total + 48;
}
//num1 is the this object
cout << this->numArr[NUM_DIGITS];
//num2 is the rightOperand object
cout << rightOperand.numArr[NUM_DIGITS];
return objToReturn;
}
BigInt BigInt::operator+(const BigInt& rightOperand){
return add(rightOperand);
}
string BigInt::convertToString(){
// TODO: VALUE IN numArr CONVERTED TO STRING
int count = 0;
string str;
if(numArr[0] == 57){
tensComplement();
}
for (int i = 0; i < NUM_DIGITS; i++){
if(numArr[i] == 48 && count == 0){
}else{
str.push_back(numArr[i]);
count++;
}
}
return str;
}
void BigInt::tensComplement(){
// TODO: TENS COMPLEMENT OF THIS NUMBER
for (int i = 0; i <= 100; i++) {
numArr[i] = 9 - numArr[i];
}
numArr[NUM_DIGITS] += 1;
for(int i = NUM_DIGITS; i >= 1; i--){
if(numArr[i] == 10){
numArr[i] = 0;
numArr[i - 1] += 1;
}
}
if(numArr[0] == 1){
numArr[0] = 9;
}
}
//This helps with testing.
bool checkTest(string testName, string whatItShouldBe, string whatItIs) {
if (whatItShouldBe == whatItIs) {
cout << "Passed " << testName << " last digit was: " << whatItIs.at(whatItIs.length()-1) << endl;
return true;
}
else {
if (whatItShouldBe == "") {
cout << "**Failed test " << testName << " ** " << endl << " Output was "<< whatItIs << endl << " Output should have been blank. " << endl;
} else {
cout << "**Failed test " << testName << " ** " << endl << " Output was "<< whatItIs << endl << " Output should have been " << whatItShouldBe << endl;
}
return false;
}
}

This looks like "home-work" but any way.
You would probably benefit from detecting negative values in the constructor and storing that information in a flag. This makes it easier to decide how to use the number in calculations.
As Roddy said you would probably benefit from keeping the digits as numbers instead of characters, reasonably you would be implementing more calculations than displays in BigInt and you will not need to convert things for each calculation, just imagine what it would be like to handle multiplication and division like you do add.
You might benefit from implementing the subtract method before trying to make "add" do subtraction.
I would guess you have two main problems with subtraction,
the four permutations of signs and "borrowing" instead of carry.
Have you planed for any compare method?
main() for testing would give you more value if you kept all your tests in it.
The main in your question have only one assert.
If you keep the asserts for the already implemented functionality you ensure that it keeps working while you add new behavior.
Try to figure out your edge cases and keep a test for each.
Also try to remember that you do not need to implement the whole functionality at once, verifying a small piece that you can see how to do might help you to reason about the rest of the problem.
Your "checkTest" function returns a boolean, use it to count the number of failed tests and return that to give you the ability to fail the build when any test fails.
You need to have a return value telling if any test failed, because in a larger build test-failures will disappear in the noise unless they "scream" at you, e.g. by failing the build.
I hope this helps you find a solution and learn from the problem.

Related

C++ terminate called after throwing an instance of 'std::invalid_argument'

I just wrote this program. The test case I am using is 541. It is supposed to reverse the 541 into 154, then subtract 541 and 154, to get 396 then reverse that into 693. After that it is supposed to add 396 and 693 to get 1089. In the last three lines of code, I am trying to convert the strings into ints so I can add the last two numbers but I am getting this error. The code has to be done in this specific way for my class.
#include <iostream>
#include <string>
#include <algorithm>
/**
* main application starting point
* #return integer (0=SUCCESS)
*/
int main() {
//prompts user to input a three-digit number
std::string threeDigitNum;
std::cout << "Enter a 3-digit number, where the first and last digit differ by at least one" ;
std::cin >> threeDigitNum;
//uses a for loop to output the reverse of the first number
std::string threeReversed;
int control = 0;
for(int i = 2; i >= 0; i--){
threeReversed[control] = threeDigitNum[i];
control++;
}
std::cout << threeDigitNum[2]+ threeDigitNum[1]+ threeDigitNum[0] << std::endl;
//converts the numbers in the strings to integers
//displays the differnce of the first and second number
int firstNum = std::stoi(threeDigitNum);
int secondNum = std::stoi(threeReversed);
std::cout << firstNum - secondNum << std::endl;
std::string thirdNum;
thirdNum = std::to_string(firstNum - secondNum);
std::string thirdNumReverse;
for(int i = thirdNum.length(); i >= 0; i--){
thirdNumReverse = thirdNumReverse + thirdNum[i];
}
std::cout << thirdNumReverse << std::endl;
int fourthNum = std::stoi(thirdNum);
int fifthNum = std::stoi(thirdNumReverse);
std::cout<< fourthNum + fifthNum;
return 0;
}
Here's a hint:
std::string thirdNumReverse;
for(int i = thirdNum.length(); i >= 0; i--){
thirdNumReverse = thirdNumReverse + thirdNum[i];
}
If the length of thirdNum is 3, then the valid indices are from [2..0]. But yor code enumerates a different range of indices.
You are creating an empty string
std::string threeReversed;
and then you try to write into that empty (!) string using the subscript operator (using positions which don't exist in that string).
threeReversed[control] = threeDigitNum[i];
If you want to reverse a string, you can use a C++ Standard Library algorithm:
std::string threeReversed{ threeDigitNum };
std::reverse(threeReversed.begin(), threeReversed.end());
Later in the code, you have the same issue again for thirdNumReverse.
You are at a point where you want to learn how to debug small programs.
You may also want to use smaller methods which you can test on their own. See how short your code can become when you use a method that does the number reversing process for you:
#include <iostream>
#include <string>
#include <algorithm>
#include <cassert>
int reverse(int i)
{
std::string s = std::to_string(i);
std::reverse(s.begin(), s.end());
return std::stoi(s);
}
int main() {
assert(reverse(541) == 145);
int threeDigitNum{541};
int threeReversed = reverse(threeDigitNum);
std::cout << threeReversed << std::endl;
std::cout << threeDigitNum - threeReversed << std::endl;
int thirdNum = threeDigitNum - threeReversed;
int thirdNumReverse = reverse(thirdNum);
std::cout << thirdNumReverse << std::endl;
std::cout << thirdNum + thirdNumReverse;
return 0;
}
There are 2 errors in your code :
Error 1 : Creating empty string, but accessing other indices.
std::string threeReversed;
int control = 0;
for(int i = 2; i >= 0; i--){
threeReversed[control] = threeDigitNum[i];
control++;
}
change above code as you already did while calculating thirdNumReverse :
std::string threeReversed;
for(int i = 2; i >= 0; i--){
threeReversed = threeReversed + threeDigitNum[i];
}
Error 2 : indices are 0 based in c++, so start from thirdNum.length() - 1 instead of thirdNum.length()
for(int i = thirdNum.length(); i >= 0; i--){
thirdNumReverse = thirdNumReverse + thirdNum[i];
}
change above code as below :
for(int i = thirdNum.length() - 1; i >= 0; i--){
thirdNumReverse = thirdNumReverse + thirdNum[i];
}
Note : This code can be improved but I am just pointing out the errors in your existing code. Not improving it.

Vectors with binary search in c++

My code doesn't seem to work and I cannot understand why.
When the user enters a number to search for its location it doesn't show anything. If anyone could explain it to me I would greatly appreciate it.
void Array::binarySearch(vector<int> vect)
{
int search_val;
int high = (int)vect.size();
int low = 0;
int mid = 0;
bool found = false;
cout << "Enter Number to search : ";
cin>>search_val;
while (low <= high && !found) {
mid = (high + low)/2;
if (search_val > vect[mid]) {
low = mid + 1;
} else if (search_val < vect[mid]) {
high = mid - 1;
} else {
cout << "Number you entered " << search_val << " was found in position " << mid << endl;
found = true;
}
}
if (!found) {
cout << " The value isn't found " << endl;
}
}
sorted algo:
void Array::arrSort(vector<int> vect)
{
for (unsigned int i = 0; i < vect.size()-1; i++)
{
for (unsigned int j = 0; j < vect.size()-i-1; j++)
{
if (vect[j] > vect[j+1])
{
int x = vect[j+1];
vect[j+1] = vect[j];
vect[j] = x;
}
}
}
cout<<"Sorted output is "<<endl;
printArr(vect);
}
Your arrSort function takes its parameter by value, so it receives (and sorts) a copy of the original array.
To sort the array you're passing in, take the parameter by reference:
void Array::arrSort(vector<int> &vect)
As someone has pointed out, you must ensure that you are performing binary search on a sorted array. Perhaps, you should build and test each algorithm separately to ensure correctness before combining them together.
Check out std::sort to get your binary search function working, then work on your sort function––or vice versa.
Also, if you have found the item you are looking for say, vect[mid] == search_val you can go ahead and return true (or print like you've done) and terminate the algorithm.

Prevent loop from echoing if another same-value array element has been already echoed in C++

First of all, sorry for the mis-worded title. I couldn't imagine a better way to put it.
The problem I'm facing is as follows: In a part of my program, the program counts occurences of different a-zA-Z letters and then tells how many of each letters can be found in an array. The problem, however, is this:
If I have an array that consists of A;A;F;A;D or anything similar, the output will be this:
A - 3
A - 3
F - 1
A - 3
D - 1
But I am required to make it like this:
A - 3
F - 1
D - 1
I could solve the problem easily, however I can't use an additional array to check what values have been already echoed. I know why it happens, but I don't know a way to solve it without using an additional array.
This is the code snippet (the array simply consists of characters, not worthy of adding it to the snippet):
n is the size of array the user is asked to choose at the start of the program (not included in the snippet).
initburts is the current array member ID that is being compared against all other values.
burts is the counter that is being reset after the loop is done checking a letter and moves onto the next one.
do {
for (i = 0; i < n; i++) {
if (array[initburts] == array[i]) {
burts++;
}
}
cout << "\n\n" << array[initburts] << " - " << burts;
initburts++;
burts = 0;
if (initburts == n) {
isDone = true;
}
}
while (isDone == false);
Do your counting first, then loop over your counts printing the results.
std::map<decltype(array[0]), std::size_t> counts;
std::for_each(std::begin(array), std::end(array), [&counts](auto& item){ ++counts[item]; });
std::for_each(std::begin(counts), std::end(counts), [](auto& pair) { std::cout << "\n\n" << pair.first << " - " pair.second; });
for (i = 0; i < n; i++)
{
// first check if we printed this character already;
// this is the case if the same character occurred
// before the current one:
bool isNew = true;
for (j = 0; j < i; j++)
{
// you find out yourself, do you?
// do not forget to break the loop
// in case of having detected an equal value!
}
if(isNew)
{
// well, now we can count...
unsigned int count = 1;
for(int j = i + 1; j < n; ++j)
count += array[j] == array[i];
// appropriate output...
}
}
That would do the trick and retains the array as is, however is an O(n²) algorithm. More efficient (O(n*log(n))) is sorting the array in advance, then you can just iterate over the array once. Of course, original array sequence gets lost then:
std::sort(array, array + arrayLength);
auto start = array;
for(auto current = array + 1; current != array + arrayLength; ++current)
{
if(*current != *start)
{
auto char = *start;
auto count = current - start;
// output char and count appropriately
}
}
// now we yet lack the final character:
auto char = *start;
auto count = array + arrayLength - start;
// output char and count appropriately
Pointer arithmetic... Quite likely that your teacher gets suspicious if you just copy this code, but it should give you the necessary hints to make up your own variant (use indices instead of pointers...).
I would do it this way.
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
string s;
vector<int> capCount(26, 0), smallCount(26, 0);
cout << "Enter the string\n";
cin >> s;
for(int i = 0; i < s.length(); ++i)
{
char c = s.at(i);
if(c >= 'A' && c <= 'Z')
++capCount[(int)c - 65];
if(c >= 'a' && c <= 'z')
++smallCount[(int)c - 97];
}
for(int i = 0; i < 26; ++i)
{
if(capCount[i] > 0)
cout << (char) (i + 65) << ": " << capCount[i] << endl;
if(smallCount[i] > 0)
cout << (char) (i + 97) << ": " << smallCount[i] << endl;
}
}
Note: I have differentiated lower and upper case characters.
Here's is the sample output:
output

Vector cannot be overwritten

I'm trying to write a program for university. The goal of the program is to make a nurse schedule for a hospital. However, i'm really stuck for the moment. Below you can find one function of the program.
The input for the function is a roster which consists of the shift each nurse has to perform on each day. In this example, we have 32 rows (32 nurses) and 28 columns (representing 28 days). Each cell contains a number from 0 to 6, indicating a day off (0) or a certain shift (1 to 6).
The function should calculate for each day, how many nurses are scheduled for a certain shift. For example, on the first day, there are 8 nurses which perform shift 2, 6 shift 3 and so forth. The output of the function is a double vector.
I think the function is mostly correct but when I call it for different rosters the program always gives the first roster gave.
void calculate_nbr_nurses_per_shift(vector<vector<int>> roster1)
{
for (int i = 0; i < get_nbr_days(); i++)
{
vector<int> nurses_per_shift;
int nbr_nurses_free = 0;
int nbr_nurses_shift1 = 0;
int nbr_nurses_shift2 = 0;
int nbr_nurses_shift3 = 0;
int nbr_nurses_shift4 = 0;
int nbr_nurses_shift5 = 0;
int nbr_nurses_shift6 = 0;
for (int j = 0; j < get_nbr_nurses(); j++)
{
if (roster1[j][i] == 0)
nbr_nurses_free += 1;
if (roster1[j][i] == 1)
nbr_nurses_shift1 += 1;
if (roster1[j][i] == 2)
nbr_nurses_shift2 += 1;
if (roster1[j][i] == 3)
nbr_nurses_shift3 += 1;
if (roster1[j][i] == 4)
nbr_nurses_shift4 += 1;
if (roster1[j][i] == 5)
nbr_nurses_shift5 += 1;
if (roster1[j][i] == 6)
nbr_nurses_shift6 += 1;
}
nurses_per_shift.push_back(nbr_nurses_shift1);
nurses_per_shift.push_back(nbr_nurses_shift2);
nurses_per_shift.push_back(nbr_nurses_shift3);
nurses_per_shift.push_back(nbr_nurses_shift4);
nurses_per_shift.push_back(nbr_nurses_shift5);
nurses_per_shift.push_back(nbr_nurses_shift6);
nurses_per_shift.push_back(nbr_nurses_free);
nbr_nurses_per_shift_per_day.push_back(nurses_per_shift);
}
}
Here you can see the program:
Get_shift_assignment() and schedule_LD are other rosters.
void test_schedule_function()
{
calculate_nbr_nurses_per_shift(schedule_LD);
calculate_nbr_nurses_per_shift(get_shift_assignment());
calculate_coverage_deficit();
}
One more function you need to fully understand the problem is this one:
void calculate_coverage_deficit()
{
int deficit = 0;
for (int i = 0; i < get_nbr_days(); i++)
{
vector<int> deficit_day;
for (int j = 0; j < get_nbr_shifts(); j++)
{
deficit = get_staffing_requirements()[j] - nbr_nurses_per_shift_per_day[i][j];
deficit_day.push_back(deficit);
}
nurses_deficit.push_back(deficit_day);
}
cout << "Day 1, shift 1: there is a deficit of " << nurses_deficit[0][0] << " nurses." << endl;
cout << "Day 1, shift 2: there is a deficit of " << nurses_deficit[0][1] << " nurses." << endl;
cout << "Day 1, shift 3: there is a deficit of " << nurses_deficit[0][2] << " nurses." << endl;
cout << "Day 1, shift 4: there is a deficit of " << nurses_deficit[0][3] << " nurses." << endl;
}
So the problem is that each time I run this program it always gives me the deficits of the first roster. In this case, this is Schedule_LD. When I first run the function with input roster get_shift_assignment() than he gives me the deficits for that roster.
Apparently the nbr_nurses_per_shift_per_day[][] vector is not overwritten the second time I run the function and I don't know how to fix this... Any help would be greatly appreciated.
Let me try to summarize the comments:
By using global variables to return values from your functions it is very likely, that you forgot to remove older results from one or more of your global variables before calling functions again.
To get around this, return your results from the function instead.
Ex:
vector<vector<int>> calculate_nbr_nurses_per_shift(vector<vector<int>> roster1)
{
vector<int> nbr_nurses_per_shift_per_day; // Create the result vector
... // Do your calculations
return nbr_nurses_per_shift_per_day;
}
or if you do not want to return a vector:
void calculate_nbr_nurses_per_shift(vector<vector<int>> roster1, vector<vector<int>> nbr_nurses_per_shift_per_day)
{
... // Do your calculations
}
But clearly, the first variant is a lot less error-prone (in the second example you can forget to clear nbr_of_nurses again) and most compilers will optimize the return nbr_nurses_per_shift_per_day so the whole vector does not get copied.
The second possible issue is that ´get_nbr_days()´ might return numbers that are larger or smaller than the actual size of your vector. To work around this, use either the size() method of vector or use iterators instead.
Your first function would then look like this:
vector<vector<int>> calculate_nbr_nurses_per_shift(vector<vector<int>> roster1)
{
vector<vector<int>> nbr_nurses_per_shift_per_day;
for (vector<vector<int>>::iterator shiftsOnDay = roster1.begin(); shiftsOnDay != roster1.end(); ++shiftsOnDay)
{
vector<int> nurses_per_shift(6, 0); // Create vector with 6 elements initialized to 0
for (vector<int>::iterator shift = shiftsOnDay->begin(); shift != shiftsOnDay->end(); ++shift)
{
if (*shift == 0)
nurses_per_shift[5]++;
else
nurses_per_shift[*shift - 1]++; // This code relies on shift only containing meaningful values
}
nbr_nurses_per_shift_per_day.push_back(nurses_per_shift);
}
return nbr_nurses_per_shift_per_day;
}

c++ Genetic Algorithm Mutation error

I Have a problem with the mutation function within my genetic Algorithm. I can't quite see what I am doing wrong either. I've looked at this code for a while and I think the logic is correct, it's just not producing the results i want.
The problem
When i output the Binary array located in the Child Struct, If mutation has occured on any of the bits, then a random number will be changed, and not the one that should be.
for example
0000000 is the binary string
mutation has occured on the second
bit
0001000 would be the result
This section is located within the main.
for (int Child = 0; Child < ParentNumberInit; Child++)
{
cout << endl;
mutation(child[Child],Child);
}
This is the mutation function
void mutation(struct Parent Child1,int childnumber)
{
int mutation; // will be the random number generated
cout << endl << "Child " << (childnumber+1) << endl;
//loop through every bit in the binary string
for (int z = 0; z < Binscale; z++)
{
mutation = 0; // set mutation at 0 at the start of every loop
mutation = rand()%100; //create a random number
cout << "Generated number = " << mutation << endl;
//if variable mutation is smaller, mutation occurs
if (mutation < MutationRate)
{
if(Child1.binary_code[z] == '0')
Child1.binary_code[z] = '1';
else if(Child1.binary_code[z] == '1')
Child1.binary_code[z] = '0';
}
}
}
It's being outputted in the main like this
for (int childnumber = 0; childnumber < ParentNumberInit; childnumber++)
{
cout<<"Child "<<(childnumber+1)<<" Binary code = ";
for (int z = 0; z < Binscale; z ++)
{
cout<<child[childnumber].binary_code[z];
}
cout<<endl;
}
You can't throttle the multation rate this way. You need to separate the mutated bit from the probability of the mutation occuring.
for (int z = 0; z < Binscale; z++)
{
if (rand() % 100 < MutationRate)
{
// flip bit
Child1.binary_code[z] += 1;
Child1.binary_code[z] %= 2;
}
}
Even simpler way to flip bit:
Child1.binary_code[z] ^= 1;
try this:
void mutation(Parent& Child1,int childnumber)