C++ statement is ignored in function - c++

I have this test program and it seems like some statements inside a function (gcd()) are ignored. The std::cout statement seems to be ignored since nothing is printed to the screen with that statement. The if statement seems to be ignored because a and b were less than zero and b was positive whether that if statement was there or not (a and b remained the same).
I can't figure out why. Why are the two statements marked (with comment) are ignored?
#include <iostream>
#include <boost/multiprecision/cpp_int.hpp>
template <typename T> T gcd(T a, T b)
{
T remainder{a % b};
while (remainder != 0)
{
a = b;
b = remainder;
std::cout << remainder << '\n'; // ignored
remainder = a % b;
}
if (a < 0 && b < 0) b *= -1; // ignored
return b;
}
int main(int argc, char* argv[])
{
if (argc != 3)
{
std::cerr << '\n' <<
"Invalid number of argument(s)\n" <<
'\n' <<
"Usage: [number] [number]\n" <<
'\n';
return -1;
}
boost::multiprecision::cpp_int a{0}, b{0};
try
{
a = boost::multiprecision::cpp_int{argv[1]};
b = boost::multiprecision::cpp_int{argv[2]};
}
catch (...)
{
std::cerr << '\n' <<
"Invalid argument(s) or numbers too large/small\n" <<
'\n' <<
"Usage: [number] [number]\n" <<
'\n';
return -1;
}
const boost::multiprecision::cpp_int vgcd = gcd(a, b); // call to gcd()
std::cout << '\n' <<
"GCD (Greatest Common Divisor) test program using Euclid's algorithm (iterative)\n" <<
'\n' <<
"GCD(a, 0) = a\n" <<
"GCD(a, b) = GCD(b, a % b)\n" <<
'\n' <<
"GCD = " << vgcd << " Simplified fraction: " << a / vgcd << " / " << b / vgcd << '\n' <<
'\n';
}

You didn't actually call your gcd. boost::multiprecision provides its own gcd function, which is a better match than your template and picked up by ADL in your gcd(a, b).
Suppress ADL with ::gcd(a, b) or (gcd)(a, b) and you'll see your function template get called.

Related

less-than operator doesn't work properly after few executions

I'm a beginner to learning C++. Just today I tried to learn the boolean operator and if-else statement.
This is the code:
int main(){
//if-else statement
int a, b;
bool result = (a < b);
std::cout << "input number 1 : ";
std::cin >> a;
std::cout << "input number 2 : ";
std::cin >> b;
std::cout << std::boolalpha << result <<std::endl;
if(result == true){
std::cout << a << " is less than " << b << std::endl;
}
if(!(result == true)){
std::cout << a << " is NOT less than " << b << std::endl;
}
return 0;
}
These are the results after a few executions:
Initially the results were fine, but then after a couple times it went wrong.
Does anybody know what the cause of this is?
Your mistake is that you compare the two variables and save the result before you assign any proper values to these variables. In other words, you compare uninitialized variables a and b which have undefined values.
First, you do:
bool result = (a < b);
And then after you get the values:
std::cin >> a;
std::cin >> b;
You should do the following instead:
// ...
int a, b;
std::cout << "input number 1 : ";
std::cin >> a;
std::cout << "input number 2 : ";
std::cin >> b;
bool result = a < b; // <-- move this down here!
// ...
You expect result to be evaluate a == b when you use it later. Instead bool result = (a < b); initializes result with (a < b) once and its value does not change afterwards. As neither a nor b are initialized when you declare result your code has undefined behavior.
You can make result a function object to make it work as you expected by using a lambda expression. However, to call it you'll have to add ():
int main(){
//if-else statement
int a = 0;
int b = 0;
auto result = [&](){ return a < b; };
std::cout << "input number 1 : ";
std::cin >> a;
std::cout << "input number 2 : ";
std::cin >> b;
std::cout << std::boolalpha << result() <<std::endl;
if(result()) {
std::cout << a << " is less than " << b << std::endl;
} else {
std::cout << a << " is NOT less than " << b << std::endl;
}
}
You should always initialize variables. Using the value of uninitialized variables is undefined behavior and can happen easily (as in your code) when you do not initialize variables. Instead of if (condition) {} if (!condition){} you can use if (condition) {} else {}. Instead of if (result() == true) you can write if (result()). And return 0; is implicit in main, you need not write it.
You overall code as it should be.
Explanations in the comments:
int main() {
//if-else statement
int a, b;
std::cout << "input number 1 : ";
std::cin >> a;
std::cout << "input number 2 : ";
std::cin >> b;
bool result = (a < b); // put this here, because now a and b have
// determined values
std::cout << std::boolalpha << result << std::endl;
if (result) { // or simple if (a < b) and drop result alltogether
std::cout << a << " is less than " << b << std::endl;
}
else { // no need for testing the opposite of result
std::cout << a << " is NOT less than " << b << std::endl;
}
return 0;
}

Program that finds the number you are thinking doesn't work properly, what is wrong?

Im having trouble with this recursion code. Basically I want the computer to "guess" in as little steps as possible the number that I am thinking of. However, everything works except the final output. The bounds are fine, and it narrows down the guess until it asks me if the number im thinking of is say 16, if I input "=" it should output 16 instead it always outputs 50. Could anyone help me locate the error?
#include <iostream>
#include <cmath>
#include <string>
using namespace std;
unsigned int search (unsigned int boundInf, unsigned int boundSup);
int main ()
{
int b;
b = search (1, 100);
cout << "Your number must be : " << b << endl;
}
unsigned int search (unsigned int boundInf, unsigned int boundSup)
{
string magnitude;
int b;
b = (boundSup + boundInf) / 2;
cout << "Is your number <, > or = to " << b << "? ";
cin >> magnitude;
if (magnitude == "<") {
cout << "Between " << boundInf << " and " << b << endl;
search (boundInf, b);
}
else if (magnitude == ">") {
cout << "Between " << b << " and " << boundSup << endl;
search (b, boundSup);
}
return b;
}
You forgot to change the value of b when going deeper into the recursive function, this can be easily fixed by changing the search function like so:
unsigned int search(unsigned int boundInf, unsigned int boundSup)
{
string magnitude;
int b;
b = (boundSup + boundInf) / 2;
cout << "Is your number <, > or = to " << b << "? ";
cin >> magnitude;
if (magnitude == "<")
{
cout << "Between " << boundInf << " and " << b << endl;
b = search(boundInf, b);
}
else if (magnitude == ">")
{
cout << "Between " << b << " and " << boundSup << endl;
b = search(b, boundSup);
}
return b;
}

Recursive function showing segmentation issue C++

This code is for recursive function practice. When I run the code, it stops at the "POWER" cout line, then my compiler shows a segmentation error. The function that follows the POWER line is supposed to recursively raise number "a" to the power of number "b". I'm not sure how to fix this, can anyone help?
#include <iostream>
#include <string>
#include <vector>
using namespace std;
/**** Recursive backwards print, prints a string starting from last index to first*****/
void printReverse(string s, int i)
{
if(i < s.size())
{
printReverse(s.substr(1), i);
cout<<s[i];
}
else
{
return;
}
}
/**** Recursive power function, computes a^b, where b can be positive or negative*****/
int recPower(double a, int b)
{
int i = b; //i = b, so int a can be multiplied int b times
if (i == 0) //base
return 1;
else //multiply A by B, B times
{
a *= b;
return recPower(a, b); //recursive
i--; //decrement i until it equals 0
}
}
/**** Recursive string replace, replaces all instances of a character in a string with another character*****/
string recReplace(string s2, int i, char old, char neW)
{
if(s2[i] == old) //search for old char
{
i = neW; //replace it
i++; //iterate i
}
recReplace(s2, i, old, neW); //call function
return s2;
}
/**** Recursive list find > Searches if x exists in list, returns true if found, false otherwise*****/
int recListFind(vector<int> v, int i, int x)
{
if(v[i] == x)
{
cout << x << " exists in the vector."<<endl;
i++;
recListFind(v, i, x);
}
return true;
}
int main()
{
cout << "PRINT REVERSE" << endl;
cout << "----------" << endl;
string s1 = "hello world";
cout << "String: " << s1 << endl;
cout << "Reversed: ";
printReverse(s1, 0);
cout << endl;
/* Computes a^b (power function) */
cout << "POWER" << endl;
cout << "----------" << endl;
int a = 2, b = -3;
cout << a << "^" << b << " = ";
cout << recPower(a, b) << endl;
cout << endl;
/* Replaces a character in a string with a new one */
cout << "REPLACE" << endl;
cout << "----------" << endl;
string s2 = "-h-e-l-l-o-";
char oldChar = '-';
char newChar = ' ';
cout << "String: " << s2 << endl;
cout << "> Replace '" << oldChar << "' with '" << newChar << endl;
recReplace(s2, 0, oldChar, newChar);
cout << "String: " << s2 << endl;
cout << endl;
/* Searches for value in vector */
cout << "FIND" << endl;
cout << "----------" << endl;
int x = 7;
cout << "Does " << x << " exist in the vector? "; vector<int> v = {5, 1, 6, 7, 9};
cout << recListFind(v, 0, 7) << endl;
cout << endl;
return 0;
}
The issue is quite straight forward, you are doing the recPower function with b. In the function, if b is not 0, you call recPower with an unmodified value of b (whilst ever modifying a). This will always end up with infinite recursion which is going to overflow your stack.
A solution could be:
int recPower(double a, int b, int times) {
if (times == 0)
return a;
else
return b * recPower(a, b, --times);
}
int recPower(double a, int b) {
return recPower(a, b, b);
}
Even if you fix this, you have another problem. b can be negative, which based on your logic will continue to recurse while decrementing until it overflows and goes back to 0. You will cause this case with your first test case. You should think about the types that are allowed in this function, consider making them unsigned, or dealing explicitly with the negative b case.

Integer overflow and std::stoi

if x > INT_MAX or if x > INT_MIN the function will return 0... or that's what i'm trying to do :)
in my test case i pass in a value that is INT_MAX + 1... 2147483648 ... to introduce integer overflow to see how the program handles it.
i step through... my IDE debugger says that the value immediately goes to -2147483648 upon overflow and for some reason the program executes beyond both of these statements:
if (x > INT_MAX)
if (x < INT_MIN)
and keeps crashes at int revInt = std::stoi(strNum);
saying out of range
Must be something simple, but it's got me stumped. Why isn't the program returning before it ever gets to that std::stoi() given x > INT_MAX? Any help appreciated. Thanks! Full listing of function and test bed below: (sorry having trouble with the code insertion formatting..)
#include <iostream>
#include <algorithm>
#include <string> //using namespace std;
class Solution {
public: int reverse(int x)
{
// check special cases for int and set flags:
// is x > max int, need to return 0 now
if(x > INT_MAX)
return 0;
// is x < min int, need to return 0 now
if(x < INT_MIN)
return 0;
// is x < 0, need negative sign handled at end
// does x end with 0, need to not start new int with 0 if it's ploy numeric and the functions used handle that for us
// do conversion, reversal, output:
// convert int to string
std::string strNum = std::to_string(x);
// reverse string
std::reverse(strNum.begin(), strNum.end());
// convert reversed string to int
int revInt = std::stoi(strNum);
// multiply by -1 if x was negative
if (x < 0)
revInt = revInt * -1;
// output reversed integer
return revInt;
}
};
Main:
#include <iostream>
int main(int argc, const char * argv[]) {
// test cases
// instance Solution and call it's method
Solution sol;
int answer = sol.reverse(0); // 0
std::cout << "in " << 0 << ", out " << answer << "\n";
answer = sol.reverse(-1); // -1
std::cout << "in " << -1 << ", out " << answer << "\n";
answer = sol.reverse(10); // 1
std::cout << "in " << 10 << ", out " << answer << "\n";
answer = sol.reverse(12); // 21
std::cout << "in " << 12 << ", out " << answer << "\n";
answer = sol.reverse(100); // 1
std::cout << "in " << 100 << ", out " << answer << "\n";
answer = sol.reverse(123); // 321
std::cout << "in " << 123 << ", out " << answer << "\n";
answer = sol.reverse(-123); // -321
std::cout << "in " << -123 << ", out " << answer << "\n";
answer = sol.reverse(1024); // 4201
std::cout << "in " << 1024 << ", out " << answer << "\n";
answer = sol.reverse(-1024); // -4201
std::cout << "in " << -1024 << ", out " << answer << "\n";
answer = sol.reverse(2147483648); // 0
std::cout << "in " << 2147483648 << ", out " << answer << "\n";
answer = sol.reverse(-2147483648); // 0
std::cout << "in " << -2147483648 << ", out " << answer << "\n";
return 0;
}
Any test like (x > INT_MAX) with x being of type int will never evaluate to true, since the value of x cannot exceed INT_MAX.
Anyway, even if 2147483647 would be a valid range, its reverse 7463847412 is not.
So I think its better to let stoi "try" to convert the values and "catch" any out_of_range-exception`. The following code illustrates this approach:
int convert() {
const char* num = "12345678890123424542";
try {
int x = std::stoi(num);
return x;
} catch (std::out_of_range &e) {
cout << "invalid." << endl;
return 0;
}
}

Significant figures in C++

I've written a program that calculates values in a series and all of the values are particularly lengthy doubles. I want to print these values each displaying 15 significant figures. Here's some code that illustrates the issue I'm having:
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
double x = 0.12345678901234567890;
double y = 1.12345678901234567890;
cout << setprecision(15) << fixed << x << "\t" << y << "\n";
return 0;
}
With just setprecision trailing zeros are not shown so I added fixed as I have seen in other answers on this site. However, now I just seem to have 15 decimal places and for values that aren't 0.something this is not what I want. You can see this from the output of the above:
0.123456789012346 1.123456789012346
The first number has 15 sig figs but the second has 16. What can I do to resolve this?
EDIT: I have been specifically asked to use setprecision, so I am unable to try cout.precision.
You can simply use scientific (note the 14 instead of 15):
std::cout << std::scientific << std::setprecision(14) << -0.123456789012345678 << std::endl;
std::cout << std::scientific << std::setprecision(14) << -1.234567890123456789 << std::endl;
-1.23456789012346e-01
-1.23456789012346e+00
or you can use a function:
#include <iostream>
#include <vector>
#include <iomanip>
#include <string>
#include <sstream>
enum vis_opt { scientific, decimal, decimal_relaxed };
std::string figures(double x, int nfig, vis_opt vo=decimal) {
std::stringstream str;
str << std::setprecision(nfig-1) << std::scientific << x;
std::string s = str.str();
if ( vo == scientific )
return s;
else {
std::stringstream out;
std::size_t pos;
int ileft = std::stoi(s,&pos);
std::string dec = s.substr(pos + 1, nfig - 1);
int e = std::stoi(s.substr(pos + nfig + 1));
if ( e < 0 ) {
std::string zeroes(-1-e,'0');
if ( ileft < 0 )
out << "-0." << zeroes << -ileft << dec;
else
out << "0." << zeroes << ileft << dec;
} else if ( e == 0) {
out << ileft << '.' << dec;
} else if ( e < ( nfig - 1) ) {
out << ileft << dec.substr(0,e) << '.' << dec.substr(e);
} else if ( e == ( nfig - 1) ) {
out << ileft << dec;
} else {
if ( vo == decimal_relaxed) {
out << s;
} else {
out << ileft << dec << std::string(e - nfig + 1,'0');
}
}
return out.str();
}
}
int main() {
std::vector<double> test_cases = {
-123456789012345,
-12.34567890123456789,
-0.1234567890123456789,
-0.0001234,
0,
0.0001234,
0.1234567890123456789,
12.34567890123456789,
1.234567890123456789,
12345678901234,
123456789012345,
1234567890123456789.0,
};
for ( auto i : test_cases) {
std::cout << std::setw(22) << std::right << figures(i,15,scientific);
std::cout << std::setw(22) << std::right << figures(i,15) << std::endl;
}
return 0;
}
My output is:
-1.23456789012345e+14 -123456789012345
-1.23456789012346e+01 -12.3456789012346
-1.23456789012346e-01 -0.123456789012346
-1.23400000000000e-04 -0.000123400000000000
0.00000000000000e+00 0.00000000000000
1.23400000000000e-04 0.000123400000000000
1.23456789012346e-01 0.123456789012346
1.23456789012346e+01 12.3456789012346
1.23456789012346e+00 1.23456789012346
1.23456789012340e+13 12345678901234.0
1.23456789012345e+14 123456789012345
1.23456789012346e+18 1234567890123460000
I've found some success in just computing the integer significant figures, and then setting the floating significant figures to be X - <integer sig figs>:
Edit
To address Bob's comments, I'll account for more edge cases. I've refactored the code somewhat to adjust the field precision based on leading and trailing zeros. There would still be an edge case I believe for very small values (like std::numeric_limits<double>::epsilon:
int AdjustPrecision(int desiredPrecision, double _in)
{
// case of all zeros
if (_in == 0.0)
return desiredPrecision;
// handle leading zeros before decimal place
size_t truncated = static_cast<size_t>(_in);
while(truncated != 0)
{
truncated /= 10;
--desiredPrecision;
}
// handle trailing zeros after decimal place
_in *= 10;
while(static_cast<size_t>(_in) == 0)
{
_in *= 10;
++desiredPrecision;
}
return desiredPrecision;
}
With more tests:
double a = 0.000123456789012345;
double b = 123456789012345;
double x = 0.12345678901234567890;
double y = 1.12345678901234567890;
double z = 11.12345678901234567890;
std::cout.setf( std::ios::fixed, std:: ios::floatfield);
std::cout << "a: " << std::setprecision(AdjustPrecision(15, a)) << a << std::endl;
std::cout << "b: " << std::setprecision(AdjustPrecision(15, b)) << b << std::endl;
std::cout << "x " << std::setprecision(AdjustPrecision(15, x)) << x << std::endl;
std::cout << "y " << std::setprecision(AdjustPrecision(15, y)) << y << std::endl;
std::cout << "z: " << std::setprecision(AdjustPrecision(15, z)) << z << std::endl;
Output:
a: 0.000123456789012345
b: 123456789012345
x 0.123456789012346
y 1.12345678901235
z: 11.1234567890123
Live Demo
int GetIntegerSigFigs(double _in)
{
int toReturn = 0;
int truncated = static_cast<int>(_in);
while(truncated != 0)
{
truncated /= 10;
++toReturn;
}
return toReturn;
}
(I'm sure there are some edge cases I'm missing)
And then using it:
double x = 0.12345678901234567890;
double y = 1.12345678901234567890;
std::cout << td::setprecision(15-GetIntegerSigFigs(x)) << x
<< "\t" << std::setprecision(15-GetIntegerSigFigs(y)) << y << "\n";
Prints:
0.123456789012346 1.12345678901235
Live Demo