I am writing a simple calculator program. When I try to make it do a division problem that results in a decimal eg: 1/4 or 10/3, it rounds it to the nearest whole number. How could I fix this?
I have a function that takes two numbers (x and y) and an operation (op) , and returns them:
int getAnswer(int x, int op, int y)
int getAnswer(int x, int op, int y)
{
if (op == 1)
return x + y;
if (op == 2)
return x - y;
if (op == 3)
return x * y;
if (op == 4 && y != 0)
return x / y;
if (op == 4 && y == 0)
return 3293; //When 3293 is returned, an error is displayed (not the best way to handle errors, I know)
return 3293;
}
When I input x as 10, for example, y as 3, and op as 4 (for division), it returns 10/3. My main function assigns the returned value to the variable "result". My main:
int main()
{
int input1 = getValueFromUser();
int op = getOperationFromUser();
int input2 = getValueFromUser();
int result = getAnswer(input1, op, input2 );
printResult(result);
std::cin.ignore();
std::cin.get();
return 0;
}
My printResult funcion then prints the result using std::cout, but rather than printing 3.33, it prints 3. So, this leads my to the conclusion that the variable result, has no decimal points. How would I make the variable result have decimal points?
Just in case, my printResult function looks like this:
void printResult(int result)
{
if (result != 3293)
{
std::cout << "The answer is: " << result << std::endl;
}
else
{
std::cout << "ERR: Can't Calc" << std::endl;
}
}
You need the double type to display the divisions correctly. Otherwise it gets rounded to the integer value. For example 4/3 = 1, not 1.33333
double getAnswer(double x, int op, double y)
{
if (op == 1)
return x + y;
if (op == 2)
return x - y;
if (op == 3)
return x * y;
if (op == 4 && y != 0)
return x / y;
if (op == 4 && y == 0)
return 3293; //When 3293 is returned, an error is displayed (not the best way to handle errors, I know)
return 3293;
}
int main()
{
double input1 = getValueFromUser();
int op = getOperationFromUser();
double input2 = getValueFromUser();
double result = getAnswer(input1, op, input2 );
printResult(result);
std::cin.ignore();
std::cin.get();
return 0;
}
void printResult(double result)
{
if (result != 3293)
{
std::cout << "The answer is: " << result << std::endl;
}
else
{
std::cout << "ERR: Can't Calc" << std::endl;
}
}
With a int you cant handle floating point numbers, use float or double.
You can cast your int to float for the division.
float getAnswer(int x, int y)
{
return static_cast<float>(x) / static_cast<float>(y);
}
float result = getAnswer(input1, input2 );
You need to cast your ints to double:
In your getAnswer function:
if (op == 4 && y != 0)
return static_cast<double>(x) / y;
Also make sure your getAnswer function returns double...
your result value also needs to be double, the print function should take a double, etc.
Related
I was wondering how bad floating point inaccuracies can get when normalizing vectors, specifically a 3D one. Normalizing once should give the same value as normalizing twice, but, as expected, floating point inaccuracies don't guarantee us that. So I decided to test some other things: if you normalize indefinitely, will it always "converge" to a value that normalizes to itself? The answer is no. For example, a few seconds testing and I found a value that loops between 2: -0.60445204839058564 -0.54547899327834748 -0.58059485795902943 and -0.60445204839058575 -0.54547899327834759 -0.58059485795902954. Some "converge" after 3, 5 steps. Here's my boring code:
#include <iostream>
#include <numeric>
#include <random>
using namespace std;
struct Point
{
double x, y, z;
bool operator==(const Point& o) const
{
return
x == o.x &&
y == o.y &&
z == o.z;
}
};
auto square(auto x)
{
return x * x;
}
Point normalize(const Point& p)
{
auto l = sqrt(square(p.x) + square(p.y) + square(p.z));
return { p.x / l, p.y / l, p.z / l };
}
std::mt19937 mt(24);
std::uniform_real_distribution d(-1., 1.);
int main()
{
while (true)
{
auto
x = d(mt),
y = d(mt),
z = d(mt);
Point p{ x, y, z };
auto
n1 = normalize(p),
n2 = normalize(normalize(p));
int cnt = 1;
while (n1 != n2)
{
n1 = n2;
cnt++;
n2 = normalize(n2);
auto len = square(n2.x) + square(n2.y) + square(n2.z);
if (len != 1.)
{
__debugbreak();
}
}
if (cnt != 2)
{
cout << x << ' ' << y << ' ' << z
<< " took " << cnt << '\n';
}
}
}
So I have a few curiosities:
What inputs create the longest loop/cycle and never converge?
What inputs take longest to converge?
After normalizing once, what input gives the maximum error from a length of 1?
Given a decimal floating-point value, how can you find its fractional equivalent/approximation? For example:
as_fraction(0.1) -> 1/10
as_fraction(0.333333) -> 1/3
as_fraction(514.0/37.0) -> 514/37
Is there a general algorithm that can convert a decimal number to fractional form? How can this be implemented simply and efficiently in C++?
First get the fractional part and then take the gcd. Use the Euclidean algorithm http://en.wikipedia.org/wiki/Euclidean_algorithm
void foo(double input)
{
double integral = std::floor(input);
double frac = input - integral;
const long precision = 1000000000; // This is the accuracy.
long gcd_ = gcd(round(frac * precision), precision);
long denominator = precision / gcd_;
long numerator = round(frac * precision) / gcd_;
std::cout << integral << " + ";
std::cout << numerator << " / " << denominator << std::endl;
}
long gcd(long a, long b)
{
if (a == 0)
return b;
else if (b == 0)
return a;
if (a < b)
return gcd(a, b % a);
else
return gcd(b, a % b);
}
#include <iostream>
#include <valarray>
using namespace std;
void as_fraction(double number, int cycles = 10, double precision = 5e-4){
int sign = number > 0 ? 1 : -1;
number = number * sign; //abs(number);
double new_number,whole_part;
double decimal_part = number - (int)number;
int counter = 0;
valarray<double> vec_1{double((int) number), 1}, vec_2{1,0}, temporary;
while(decimal_part > precision & counter < cycles){
new_number = 1 / decimal_part;
whole_part = (int) new_number;
temporary = vec_1;
vec_1 = whole_part * vec_1 + vec_2;
vec_2 = temporary;
decimal_part = new_number - whole_part;
counter += 1;
}
cout<<"x: "<< number <<"\tFraction: " << sign * vec_1[0]<<'/'<< vec_1[1]<<endl;
}
int main()
{
as_fraction(3.142857);
as_fraction(0.1);
as_fraction(0.333333);
as_fraction(514.0/37.0);
as_fraction(1.17171717);
as_fraction(-1.17);
}
x: 3.14286 Fraction: 22/7
x: 0.1 Fraction: 1/10
x: 0.333333 Fraction: 1/3
x: 13.8919 Fraction: 514/37
x: 1.17172 Fraction: 116/99
x: 1.17 Fraction: -117/100
Sometimes you would want to approximate the decimal, without needing the equivalence. Eg pi=3.14159 is approximated as 22/7 or 355/113. We could use the cycles argument to obtain these:
as_fraction(3.14159, 1);
as_fraction(3.14159, 2);
as_fraction(3.14159, 3);
x: 3.14159 Fraction: 22/7
x: 3.14159 Fraction: 333/106
x: 3.14159 Fraction: 355/113
(Too long for a comment.)
Some comments claim that this is not possible. But I am of a contrary opinion.
I am of the opinion that it is possible in the right interpretation, but it is too easy to misstate the question or misunderstand the answer.
The question posed here is to find rational approximation(s) to a given floating point value.
This is certainly possible since floating point formats used in C++ can only store rational values, most often in the form of sign/mantissa/exponent. Taking IEEE-754 single precision format as an example (to keep the numbers simpler), 0.333 is stored as 1499698695241728 * 2^(-52). That is equivalent to the fraction 1499698695241728 / 2^52 whose convergents provide increasingly accurate approximations, all the way up to the original value: 1/3, 333/1000, 77590/233003, 5586813/16777216.
Two points of note here.
For a variable float x = 0.333; the best rational approximation is not necessarily 333 / 1000, since the stored value is not exactly 0.333 but rather 0.333000004291534423828125 because of the limited precision of the internal representation of floating points.
Once assigned, a floating point value has no memory of where it came from, or whether the source code had it defined as float x = 0.333; vs. float x = 0.333000004; because both of those values have the same internal representation. This is why the (related, but different) problem of separating a string representation of a number (for example, a user-entered value) into integer and fractional parts cannot be solved by first converting to floating point then running floating point calculations on the converted value.
[ EDIT ] Following is the step-by-step detail of the 0.333f example.
The code to convert a float to an exact fraction.
#include <cfloat>
#include <cmath>
#include <limits>
#include <iostream>
#include <iomanip>
void flo2frac(float val, unsigned long long* num, unsigned long long* den, int* pwr)
{
float mul = std::powf(FLT_RADIX, FLT_MANT_DIG);
*den = (unsigned long long)mul;
*num = (unsigned long long)(std::frexp(val, pwr) * mul);
pwr -= FLT_MANT_DIG;
}
void cout_flo2frac(float val)
{
unsigned long long num, den; int pwr;
flo2frac(val, &num, &den, &pwr);
std::cout.precision(std::numeric_limits<float>::max_digits10);
std::cout << val << " = " << num << " / " << den << " * " << FLT_RADIX << "^(" << pwr << ")" << std::endl;
}
int main()
{
cout_flo2frac(0.333f);
}
Output.
0.333000004 = 11173626 / 16777216 * 2^(-1)
This gives the rational representation of float val = 0.333f; as 5586813/16777216.
What remains to be done is determine the convergents of the exact fraction, which can be done using integer calculations, only. The end result is (courtesy WA):
0, 1/3, 333/1000, 77590/233003, 5586813/16777216
I came up with an algorithm for this problem, but I think it is too lengthy and can be accomplished with less lines of code. Sorry about the poor indentation it is hard trying to align everything on overflow.
#include <iostream>
using namespace std;
// converts the string half of the inputed decimal number into numerical values void converting
(string decimalNumber, float&numerator, float& denominator )
{ float number; string valueAfterPoint =decimalNumber.substr(decimalNumber.find("." ((decimalNumber.length() -1) )); // store the value after the decimal into a valueAfterPoint
int length = valueAfterPoint.length(); //stores the length of the value after the decimal point into length
numerator = atof(valueAfterPoint.c_str()); // converts the string type decimal number into a float value and stores it into the numerator
// loop increases the decimal value of the numerator by multiples of ten as long as the length is above zero of the decimal
for (; length > 0; length--)
numerator *= 10;
do
denominator *=10;
while (denominator < numerator);
// simplifies the the converted values of the numerator and denominator into simpler values for an easier to read output
void simplifying (float& numerator, float& denominator) { int maximumNumber = 9; //Numbers in the tenths place can only range from zero to nine so the maximum number for a position in a position for the decimal number will be nine
bool isDivisble; // is used as a checker to verify whether the value of the numerator has the found the dividing number that will a value of zero
// Will check to see if the numerator divided denominator is will equal to zero
if(int(numerator) % int(denominator) == 0) {
numerator /= denominator;
denominator = 1;
return; }
//check to see if the maximum number is greater than the denominator to simplify to lowest form while (maximumNumber < denominator) { maximumNumber *=10; }
// the maximum number loops from nine to zero. This conditions stops if the function isDivisible is true
for(; maximumNumber > 0;maximumNumber --){
isDivisble = ((int(numerator) % maximumNumber == 0) && int(denominator)% maximumNumber == 0);
if(isDivisble)
{
numerator /= maximumNumber; // when is divisible true numerator be devided by the max number value for example 25/5 = numerator = 5
denominator /= maximumNumber; //// when is divisible true denominator be devided by themax number value for example 100/5 = denominator = 20
}
// stop value if numerator and denominator is lower than 17 than it is at the lowest value
int stop = numerator + denominator;
if (stop < 17)
{
return;
} } }
I agree completely with dxiv's solution but I needed a more general function (I threw in the signed stuff for fun because my use cases only included positive values):
#include <concepts>
/**
* \brief Multiply two numbers together checking for overflow.
* \tparam T The unsigned integral type to check for multiplicative overflow.
* \param a The multiplier.
* \param b The multicland.
* \return The result and a value indicating whether the multiplication
* overflowed.
*/
template<std::unsigned_integral T>
auto mul_overflow(T a, T b) -> std::tuple<T, bool>
{
size_t constexpr shift{ std::numeric_limits<T>::digits / 2 };
T constexpr mask{ (T{ 1 } << shift) - T{ 1 } };
T const a_high = a >> shift;
T const a_low = a & mask;
T const b_high = b >> shift;
T const b_low = b & mask;
T const low_low{ a_low * b_low };
if (!(a_high || b_high))
{
return { low_low, false };
}
bool overflowed = a_high && b_high;
T const low_high{ a_low * b_high };
T const high_low{ a_high * b_low };
T const ret{ low_low + ((low_high + high_low) << shift) };
return
{
ret,
overflowed
|| ret < low_low
|| (low_high >> shift) != 0
|| (high_low >> shift) != 0
};
}
/**
* \brief Converts a floating point value to a numerator and
* denominator pair.
*
* If the floating point value is larger than the maximum that the Tout
* type can hold, the results are silly.
*
* \tparam Tout The integral output type.
* \tparam Tin The floating point input type.
* \param f The value to convert to a numerator and denominator.
* \return The numerator and denominator.
*/
template <std::integral Tout, std::floating_point Tin>
auto to_fraction(Tin f) -> std::tuple<Tout, Tout>
{
const Tin multiplier
{
std::pow(std::numeric_limits<Tin>::radix,
std::numeric_limits<Tin>::digits)
};
uint64_t denominator{ static_cast<uint64_t>(multiplier) };
int power;
Tout num_fix{ 1 };
if constexpr (std::is_signed_v<Tout>)
{
num_fix = f < static_cast<Tin>(0) ? -1 : 1;
f = std::abs(f);
}
uint64_t numerator
{
static_cast<uint64_t>(std::frexp(f, &power) * multiplier)
};
uint64_t const factor
{
static_cast<uint64_t>(std::pow(
std::numeric_limits<Tin>::radix, std::abs(power)))
};
if (power > 0)
{
while(true)
{
auto const [res, overflow]{ mul_overflow(numerator, factor) };
if (!overflow)
{
numerator = res;
break;
}
numerator >>= 1;
denominator >>= 1;
}
}
else
{
while (true)
{
auto const [res, overflow]{ mul_overflow(denominator, factor) };
if (!overflow)
{
denominator = res;
break;
}
numerator >>= 1;
denominator >>= 1;
}
}
// get the results into the requested sized integrals.
while ((numerator > std::numeric_limits<Tout>::max()
|| denominator > std::numeric_limits<Tout>::max())
&& denominator > 1)
{
numerator >>= 1;
denominator >>= 1;
}
return
{
num_fix * static_cast<Tout>(numerator),
static_cast<Tout>(denominator)
};
}
You can call this like:
auto [n, d] { to_fraction<int8_t>(-124.777f) };
And you get n=-124, d=1;
auto [n, d] { to_fraction<uint64_t>(.33333333333333) };
gives n=6004799503160601, d=18014398509481984
#include<iostream>
#include<cmath>
#include<algorithm>
#include<functional>
#include<iomanip>
#include<string>
#include<vector>
#include <exception>
#include <sstream>
// note using std = c++11
// header section
#ifndef rational_H
#define rational_H
struct invalid : std::exception {
const char* what() const noexcept { return "not a number\n"; }};
struct Fraction {
public:
long long value{0};
long long numerator{0};
long long denominator{0};
}; Fraction F;
class fraction : public Fraction{
public:
fraction() {}
void ctf(double &);
void get_fraction(std::string& w, std::string& d, long double& n) {
F.value = (long long )n;
set_whole_part(w);
set_fraction_part(d);
make_fraction();
}
long long set_whole_part(std::string& w) {
return whole = std::stoll(w);
}
long long set_fraction_part(std::string& d) {
return decimal = std::stoll(d);
}
void make_fraction();
bool cmpf(long long&, long long&, const long double& epsilon);
int Euclids_method(long long&, long long&);
long long get_f_part() { return decimal; };
void convert(std::vector<long long>&);
bool is_negative{ false };
friend std::ostream& operator<<(std::ostream& os, fraction& ff);
struct get_sub_length;
private:
long long whole{ 0 };
long long decimal{ 0 };
};
#endif // rational_H
// definitions/source
struct get_sub_length {
size_t sub_len{};
size_t set_decimal_length(size_t& n) {
sub_len = n;
return sub_len;
}
size_t get_decimal_length() { return sub_len; }
}; get_sub_length slen;
struct coefficient {
std::vector<long long>coef;
}; coefficient C;
//compare's the value returned by convert with the original
// decimal value entered.
//if its within the tolarence of the epsilon consider it the best
//approximation you can get.
//feel free to experiment with the epsilon.
//for better results.
bool fraction::cmpf(long long& n1, long long& d1, const long double& epsilon = 0.0000005)
{
long double ex = pow(10, slen.get_decimal_length());
long long d = get_f_part(); // the original fractional part to use for comparison.
long double a = (long double)d / ex;
long double b = ((long double)d1 / (long double)n1);
if ((fabs(a - b) <= epsilon)) { return true; }
return false;
}
//Euclids algorithm returns the cofficients of a continued fraction through recursive division,
//for example: 0.375 -> 1/(375/1000) (note: for the fractional portion only).
// 1000/375 -> Remainder of 2.6666.... and 1000 -(2*375)=250,using only the integer value
// 375/250 -> Remainder of 1.5 and 375-(1*250)=125,
// 250/125 -> Remainder of 2.0 and 250-(2*125)=2
//the coefficients of the continued fraction are the integer values 2,1,2
// These are generally written [0;2,1,2] or [0;2,1,1,1] were 0 is the whole number value.
int fraction::Euclids_method(long long& n_dec, long long& exp)
{
long long quotient = 0;
if ((exp >= 1) && (n_dec != 0)) {
quotient = exp / n_dec;
C.coef.push_back(quotient);
long long divisor = n_dec;
long long dividend = exp - (quotient * n_dec);
Euclids_method(dividend, divisor); // recursive division
}
return 0;
}
// Convert is adding the elements stored in coef as a simple continued fraction
// which should result in a good approximation of the original decimal number.
void fraction::convert(std::vector<long long>& coef)
{
std::vector<long long>::iterator pos;
pos = C.coef.begin(), C.coef.end();
long long n1 = 0;
long long n2 = 1;
long long d1 = 1;
long long d2 = 0;
for_each(C.coef.begin(), C.coef.end(), [&](size_t pos) {
if (cmpf(n1, d1) == false) {
F.numerator = (n1 * pos) + n2;
n2 = n1;
n1 = F.numerator;
F.denominator = (d1 * pos) + d2;
d2 = d1;
d1 = F.denominator;
}
});
//flip the fraction back over to format the correct output.
F.numerator = d1;
F.denominator = n1;
}
// creates a fraction from the decimal component
// insures its in its abs form to ease calculations.
void fraction::make_fraction() {
size_t count = slen.get_decimal_length();
long long n_dec = decimal;
long long exp = (long long)pow(10, count);
Euclids_method(n_dec, exp);
convert(C.coef);
}
std::string get_w(const std::string& s)
{
std::string st = "0";
std::string::size_type pos;
pos = s.find(".");
if (pos - 1 == std::string::npos) {
st = "0";
return st;
}
else { st = s.substr(0, pos);
return st;
}
if (!(s.find("."))){
st = "0";
return st;
}
return st;
}
std::string get_d(const std::string& s)
{
std::string st = "0";
std::string::size_type pos;
pos = s.find(".");
if (pos == std::string::npos) {
st = "0";
return st;
}
std::string sub = s.substr(pos + 1);
st = sub;
size_t sub_len = sub.length();
slen.set_decimal_length(sub_len);
return st;
}
void fraction::ctf(double& nn)
{
//using stringstream for conversion to string
std::istringstream is;
is >> nn;
std::ostringstream os;
os << std::fixed << std::setprecision(14) << nn;
std::string s = os.str();
is_negative = false; //reset for loops
C.coef.erase(C.coef.begin(), C.coef.end()); //reset for loops
long double n = 0.0;
int m = 0;
//The whole number part will be seperated from the decimal part leaving a pure fraction.
//In such cases using Euclids agorithm would take the reciprocal 1/(n/exp) or exp/n.
//for pure continued fractions the cf must start with 0 + 1/(n+1/(n+...etc
//So the vector is initilized with zero as its first element.
C.coef.push_back(m);
std::cout << '\n';
if (s == "q") { // for loop structures
exit(0);
}
if (s.front() == '-') { // flag negative values.
is_negative = true; // represent nagative in output
s.erase(remove(s.begin(), s.end(), '-'), s.end()); // using abs
}
// w, d, seperate the string components
std::string w = get_w(s);
std::string d = get_d(s);
try
{
if (!(n = std::stold(s))) {throw invalid(); } // string_to_double()
get_fraction(w, d, n);
}
catch (std::exception& e) {
std::cout << e.what();
std::cout <<'\n'<< std::endl;
}
}
// The ostream formats and displays the various outputs
std::ostream& operator<<(std::ostream& os, fraction& f)
{
std::cout << '\n';
if (f.is_negative == true) {
os << "The coefficients are [" << '-' << f.whole << ";";
for (size_t i = 1; i < C.coef.size(); ++i) {
os << C.coef[i] << ',';
}
std::cout << "]" << '\n';
os << "The cf is: " << '-' << f.whole;
for (size_t i = 1; i < C.coef.size(); ++i) {
os << "+1/(" << C.coef[i];
}
for (size_t i = 1; i < C.coef.size(); ++i) {
os << ')';
}
std::cout << '\n';
if (F.value >= 1 && F.numerator == 0 && F.denominator == 1) {
F.numerator = abs(f.whole);
os << '-' << F.numerator << '/' << F.denominator << '\n';
return os;
}
else if (F.value == 0 && F.numerator == 0 && F.denominator == 1) {
os << F.numerator << '/' << F.denominator << '\n';
return os;
}
else if (F.value == 0 && F.numerator != 0 && F.denominator != 0) {
os << '-' << abs(F.numerator) << '/' << abs(F.denominator) << '\n';
return os;
}
else if (F.numerator == 0 && F.denominator == 0) {
os << '-' << f.whole << '\n';
return os;
}
else
os << '-' << (abs(f.whole) * abs(F.denominator) + abs(F.numerator)) << '/' << abs(F.denominator) << '\n';
}
if (f.is_negative == false) {
os << "The coefficients are [" << f.whole << ";";
for (size_t i = 1; i < C.coef.size(); ++i) {
os << C.coef[i] << ',';
}
std::cout << "]" << '\n';
os << "The cf is: " << f.whole;
for (size_t i = 1; i < C.coef.size(); ++i) {
os << "+1/(" << C.coef[i];
}
for (size_t i = 1; i < C.coef.size(); ++i) {
os << ')';
}
std::cout << '\n';
if (F.value >= 1 && F.numerator == 0 && F.denominator == 1) {
F.numerator = abs(f.whole);
os << F.numerator << '/' << F.denominator << '\n';
return os;
}
else if (F.value == 0 && F.numerator != 0 && F.denominator != 0) {
os << abs(F.numerator) << '/' << abs(F.denominator) << '\n';
return os;
}
else if (F.numerator == 0 && F.denominator == 0) {
os << f.whole << '\n';
return os;
}
else
os << (abs(f.whole) * abs(F.denominator) + abs(F.numerator)) << '/' << abs(F.denominator) << '\n';
os << f.whole << ' ' << F.numerator << '/' << F.denominator << '\n';
}
return os;
}
int main()
{
fraction f;
double s = 0;
std::cout << "Enter a number to convert to a fraction\n";
std::cout << "Enter a \"q\" to quit\n";
// uncomment for a loop
while (std::cin >> s) {
f.ctf(s);
std::cout << f << std::endl;
}
// comment out these lines if you want the loop
//std::cin >> s;
//f.ctf(s);
//std::cout << f << std::endl;
}
I did a recursive function to calculate x*y with x and y are all integers (x and y >= 0). My formula is:
x * y =
0, if x is equal 0
(x >> 1)*(y << 1), if x is an even number
(x >> 1)*(y << 1) + y, if x is an odd number
"<<" and ">>" are Left Shift and Right Shift Bitwise Operator. Here is my code:
int multiply(int x, int y) {
int y1 = 0;
if (x == 0) return 0;
else if (x % 3 == 0) {
y1 = y;
x = x >> 1;
y = y << 1;
return (multiply(x, y) + y1);
}
else if (x % 2 == 0) {
x = x >> 1;
y = y << 1;
return multiply(x, y);
}
}
The recursive function above is supposed to return (x*y) value but they were all wrong when i tested and i don't know why. What did i do wrong? How can i fix this?
Your problem is wit x % 3, what happens if x = 5? you skip it. Here is improved version of your code.
int multiply(int x, int y) {
if (x == 0)
return 0;
else if (x % 2 == 1)
return (multiply(x >> 1, y << 1) + y);
return multiply(x >> 1, y << 1);
}
or maybe even this:
int multiply(int x, int y) {
if (x == 0)
return 0;
int m = multiply(x >> 1, y << 1);
if (x % 2 == 1)
m += y;
return m;
}
Here is super fast version suggested by Andy:
int multiply(int x, int y) {
if (x == 0)
return 0;
int m = multiply(x >> 1, y << 1);
if (x & 1)
m += y;
return m;
}
As a challenge of speed, here is non recursive version:
int multiply (int x, int y) {
int y1 = 0;
for (; x > 0; x = (x >> 1), y = (y << 1))
if (x&1)
y1 += y;
return y1;
}
NOTE: I know this question is about recursive method but just as a challenge I wrote non-recursive algorithm.
You are not checking if x is odd correctly here:
else if (x % 3 == 0) { // e.g. fails on x = 1
Instead, you need to do
else if (x % 2 == 1) {
Here's a demo.
Note that this makes the following else check for even values of x redundant:
else if (x % 2 == 0) { // can just be an unconditional else
Also, since you are returning from the x == 0, and x % 2 == 1 branches, the else conditions can be removed as well. You can also factor out the repeated code to make the function simpler, like this:
int multiply(int x, int y) {
if (x == 0) return 0;
if (x % 2 == 1)
return (multiply(x >> 1, y << 1) + y);
else
return multiply(x >> 1, y << 1);
}
Here's a demo.
This is what i feel is the simplest approach to carry out recursive multiplication.
Do let me know if its efficient enough for you.
#include<iostream>
using namespace std;
float multiply(float a, float b) {
//no zeros bro
if (b == 0)
return 0;
//let the recursion begin
if (b > 0)
return x + multiply(a, b - 1);
//negatives stay away pliz
if (y < 0)
return -multiply(a, -b);
}
int main() {
float a, b, result;
cout << "Enter the two numbers";
cin >> a >> b;
result = multiply(a, b);
//And the result is.................
cout << result;
return 0;
}
Recursive function related to multiplication of natural numbers:
int multCool(int a, int b)
{
return (b==1 ? a: a+ multCool(a,b-1));
}
Question:
Write C++ function to evaluate the following formula for a given x:
The following code was designed in C++ on Visual Studio to be a solution of the above mentioned problem. However whenever I run the code what I am returned is the value of x; or the same value I input.
I don't understand what the problem may be, so I would appreciate any help given.
#include <iostream>
using namespace std;
unsigned long fact(int n) {
if (n <= 1) {
return 1;
}
else {
return n * fact(n - 1);
}
}
unsigned long f(int x, int n) {
static unsigned long term;
static unsigned long sum = 0;
do {
term = pow(x, (2 * n + 1)) / fact((2 * n) + 1);
n++;
sum += term;
} while (term < 0.000001);
return sum;
}
int main() {
int y = 0;
int x;
cout << "enter x" << endl;
cin >> x;
cout << f(x, y) << endl;
system("pause");
}
I suggest you don't calculate powers and factorials on each iteration. Each next term can be generated by multiplying the previous one by x^2 / [n(n+1)]:
double sinh_in_disguise(const double x) {
const double x_sq = x * x;
double term = x;
double sum = 0;
double n = 2;
while (true) {
const double new_sum = sum + term;
if (new_sum == sum)
break;
sum = new_sum;
term *= x_sq / (n * (n + 1));
n += 2;
}
return sum;
}
int main() {
std::cout.precision(16);
double x = 2.019;
std::cout << sinh_in_disguise(x) << std::endl; // prints 3.699001094869803
std::cout << std::sinh(x) << std::endl; // prints 3.699001094869803
}
put double datatype in the whole code and it will work perfectly
Given a decimal floating-point value, how can you find its fractional equivalent/approximation? For example:
as_fraction(0.1) -> 1/10
as_fraction(0.333333) -> 1/3
as_fraction(514.0/37.0) -> 514/37
Is there a general algorithm that can convert a decimal number to fractional form? How can this be implemented simply and efficiently in C++?
First get the fractional part and then take the gcd. Use the Euclidean algorithm http://en.wikipedia.org/wiki/Euclidean_algorithm
void foo(double input)
{
double integral = std::floor(input);
double frac = input - integral;
const long precision = 1000000000; // This is the accuracy.
long gcd_ = gcd(round(frac * precision), precision);
long denominator = precision / gcd_;
long numerator = round(frac * precision) / gcd_;
std::cout << integral << " + ";
std::cout << numerator << " / " << denominator << std::endl;
}
long gcd(long a, long b)
{
if (a == 0)
return b;
else if (b == 0)
return a;
if (a < b)
return gcd(a, b % a);
else
return gcd(b, a % b);
}
#include <iostream>
#include <valarray>
using namespace std;
void as_fraction(double number, int cycles = 10, double precision = 5e-4){
int sign = number > 0 ? 1 : -1;
number = number * sign; //abs(number);
double new_number,whole_part;
double decimal_part = number - (int)number;
int counter = 0;
valarray<double> vec_1{double((int) number), 1}, vec_2{1,0}, temporary;
while(decimal_part > precision & counter < cycles){
new_number = 1 / decimal_part;
whole_part = (int) new_number;
temporary = vec_1;
vec_1 = whole_part * vec_1 + vec_2;
vec_2 = temporary;
decimal_part = new_number - whole_part;
counter += 1;
}
cout<<"x: "<< number <<"\tFraction: " << sign * vec_1[0]<<'/'<< vec_1[1]<<endl;
}
int main()
{
as_fraction(3.142857);
as_fraction(0.1);
as_fraction(0.333333);
as_fraction(514.0/37.0);
as_fraction(1.17171717);
as_fraction(-1.17);
}
x: 3.14286 Fraction: 22/7
x: 0.1 Fraction: 1/10
x: 0.333333 Fraction: 1/3
x: 13.8919 Fraction: 514/37
x: 1.17172 Fraction: 116/99
x: 1.17 Fraction: -117/100
Sometimes you would want to approximate the decimal, without needing the equivalence. Eg pi=3.14159 is approximated as 22/7 or 355/113. We could use the cycles argument to obtain these:
as_fraction(3.14159, 1);
as_fraction(3.14159, 2);
as_fraction(3.14159, 3);
x: 3.14159 Fraction: 22/7
x: 3.14159 Fraction: 333/106
x: 3.14159 Fraction: 355/113
(Too long for a comment.)
Some comments claim that this is not possible. But I am of a contrary opinion.
I am of the opinion that it is possible in the right interpretation, but it is too easy to misstate the question or misunderstand the answer.
The question posed here is to find rational approximation(s) to a given floating point value.
This is certainly possible since floating point formats used in C++ can only store rational values, most often in the form of sign/mantissa/exponent. Taking IEEE-754 single precision format as an example (to keep the numbers simpler), 0.333 is stored as 1499698695241728 * 2^(-52). That is equivalent to the fraction 1499698695241728 / 2^52 whose convergents provide increasingly accurate approximations, all the way up to the original value: 1/3, 333/1000, 77590/233003, 5586813/16777216.
Two points of note here.
For a variable float x = 0.333; the best rational approximation is not necessarily 333 / 1000, since the stored value is not exactly 0.333 but rather 0.333000004291534423828125 because of the limited precision of the internal representation of floating points.
Once assigned, a floating point value has no memory of where it came from, or whether the source code had it defined as float x = 0.333; vs. float x = 0.333000004; because both of those values have the same internal representation. This is why the (related, but different) problem of separating a string representation of a number (for example, a user-entered value) into integer and fractional parts cannot be solved by first converting to floating point then running floating point calculations on the converted value.
[ EDIT ] Following is the step-by-step detail of the 0.333f example.
The code to convert a float to an exact fraction.
#include <cfloat>
#include <cmath>
#include <limits>
#include <iostream>
#include <iomanip>
void flo2frac(float val, unsigned long long* num, unsigned long long* den, int* pwr)
{
float mul = std::powf(FLT_RADIX, FLT_MANT_DIG);
*den = (unsigned long long)mul;
*num = (unsigned long long)(std::frexp(val, pwr) * mul);
pwr -= FLT_MANT_DIG;
}
void cout_flo2frac(float val)
{
unsigned long long num, den; int pwr;
flo2frac(val, &num, &den, &pwr);
std::cout.precision(std::numeric_limits<float>::max_digits10);
std::cout << val << " = " << num << " / " << den << " * " << FLT_RADIX << "^(" << pwr << ")" << std::endl;
}
int main()
{
cout_flo2frac(0.333f);
}
Output.
0.333000004 = 11173626 / 16777216 * 2^(-1)
This gives the rational representation of float val = 0.333f; as 5586813/16777216.
What remains to be done is determine the convergents of the exact fraction, which can be done using integer calculations, only. The end result is (courtesy WA):
0, 1/3, 333/1000, 77590/233003, 5586813/16777216
I came up with an algorithm for this problem, but I think it is too lengthy and can be accomplished with less lines of code. Sorry about the poor indentation it is hard trying to align everything on overflow.
#include <iostream>
using namespace std;
// converts the string half of the inputed decimal number into numerical values void converting
(string decimalNumber, float&numerator, float& denominator )
{ float number; string valueAfterPoint =decimalNumber.substr(decimalNumber.find("." ((decimalNumber.length() -1) )); // store the value after the decimal into a valueAfterPoint
int length = valueAfterPoint.length(); //stores the length of the value after the decimal point into length
numerator = atof(valueAfterPoint.c_str()); // converts the string type decimal number into a float value and stores it into the numerator
// loop increases the decimal value of the numerator by multiples of ten as long as the length is above zero of the decimal
for (; length > 0; length--)
numerator *= 10;
do
denominator *=10;
while (denominator < numerator);
// simplifies the the converted values of the numerator and denominator into simpler values for an easier to read output
void simplifying (float& numerator, float& denominator) { int maximumNumber = 9; //Numbers in the tenths place can only range from zero to nine so the maximum number for a position in a position for the decimal number will be nine
bool isDivisble; // is used as a checker to verify whether the value of the numerator has the found the dividing number that will a value of zero
// Will check to see if the numerator divided denominator is will equal to zero
if(int(numerator) % int(denominator) == 0) {
numerator /= denominator;
denominator = 1;
return; }
//check to see if the maximum number is greater than the denominator to simplify to lowest form while (maximumNumber < denominator) { maximumNumber *=10; }
// the maximum number loops from nine to zero. This conditions stops if the function isDivisible is true
for(; maximumNumber > 0;maximumNumber --){
isDivisble = ((int(numerator) % maximumNumber == 0) && int(denominator)% maximumNumber == 0);
if(isDivisble)
{
numerator /= maximumNumber; // when is divisible true numerator be devided by the max number value for example 25/5 = numerator = 5
denominator /= maximumNumber; //// when is divisible true denominator be devided by themax number value for example 100/5 = denominator = 20
}
// stop value if numerator and denominator is lower than 17 than it is at the lowest value
int stop = numerator + denominator;
if (stop < 17)
{
return;
} } }
I agree completely with dxiv's solution but I needed a more general function (I threw in the signed stuff for fun because my use cases only included positive values):
#include <concepts>
/**
* \brief Multiply two numbers together checking for overflow.
* \tparam T The unsigned integral type to check for multiplicative overflow.
* \param a The multiplier.
* \param b The multicland.
* \return The result and a value indicating whether the multiplication
* overflowed.
*/
template<std::unsigned_integral T>
auto mul_overflow(T a, T b) -> std::tuple<T, bool>
{
size_t constexpr shift{ std::numeric_limits<T>::digits / 2 };
T constexpr mask{ (T{ 1 } << shift) - T{ 1 } };
T const a_high = a >> shift;
T const a_low = a & mask;
T const b_high = b >> shift;
T const b_low = b & mask;
T const low_low{ a_low * b_low };
if (!(a_high || b_high))
{
return { low_low, false };
}
bool overflowed = a_high && b_high;
T const low_high{ a_low * b_high };
T const high_low{ a_high * b_low };
T const ret{ low_low + ((low_high + high_low) << shift) };
return
{
ret,
overflowed
|| ret < low_low
|| (low_high >> shift) != 0
|| (high_low >> shift) != 0
};
}
/**
* \brief Converts a floating point value to a numerator and
* denominator pair.
*
* If the floating point value is larger than the maximum that the Tout
* type can hold, the results are silly.
*
* \tparam Tout The integral output type.
* \tparam Tin The floating point input type.
* \param f The value to convert to a numerator and denominator.
* \return The numerator and denominator.
*/
template <std::integral Tout, std::floating_point Tin>
auto to_fraction(Tin f) -> std::tuple<Tout, Tout>
{
const Tin multiplier
{
std::pow(std::numeric_limits<Tin>::radix,
std::numeric_limits<Tin>::digits)
};
uint64_t denominator{ static_cast<uint64_t>(multiplier) };
int power;
Tout num_fix{ 1 };
if constexpr (std::is_signed_v<Tout>)
{
num_fix = f < static_cast<Tin>(0) ? -1 : 1;
f = std::abs(f);
}
uint64_t numerator
{
static_cast<uint64_t>(std::frexp(f, &power) * multiplier)
};
uint64_t const factor
{
static_cast<uint64_t>(std::pow(
std::numeric_limits<Tin>::radix, std::abs(power)))
};
if (power > 0)
{
while(true)
{
auto const [res, overflow]{ mul_overflow(numerator, factor) };
if (!overflow)
{
numerator = res;
break;
}
numerator >>= 1;
denominator >>= 1;
}
}
else
{
while (true)
{
auto const [res, overflow]{ mul_overflow(denominator, factor) };
if (!overflow)
{
denominator = res;
break;
}
numerator >>= 1;
denominator >>= 1;
}
}
// get the results into the requested sized integrals.
while ((numerator > std::numeric_limits<Tout>::max()
|| denominator > std::numeric_limits<Tout>::max())
&& denominator > 1)
{
numerator >>= 1;
denominator >>= 1;
}
return
{
num_fix * static_cast<Tout>(numerator),
static_cast<Tout>(denominator)
};
}
You can call this like:
auto [n, d] { to_fraction<int8_t>(-124.777f) };
And you get n=-124, d=1;
auto [n, d] { to_fraction<uint64_t>(.33333333333333) };
gives n=6004799503160601, d=18014398509481984
#include<iostream>
#include<cmath>
#include<algorithm>
#include<functional>
#include<iomanip>
#include<string>
#include<vector>
#include <exception>
#include <sstream>
// note using std = c++11
// header section
#ifndef rational_H
#define rational_H
struct invalid : std::exception {
const char* what() const noexcept { return "not a number\n"; }};
struct Fraction {
public:
long long value{0};
long long numerator{0};
long long denominator{0};
}; Fraction F;
class fraction : public Fraction{
public:
fraction() {}
void ctf(double &);
void get_fraction(std::string& w, std::string& d, long double& n) {
F.value = (long long )n;
set_whole_part(w);
set_fraction_part(d);
make_fraction();
}
long long set_whole_part(std::string& w) {
return whole = std::stoll(w);
}
long long set_fraction_part(std::string& d) {
return decimal = std::stoll(d);
}
void make_fraction();
bool cmpf(long long&, long long&, const long double& epsilon);
int Euclids_method(long long&, long long&);
long long get_f_part() { return decimal; };
void convert(std::vector<long long>&);
bool is_negative{ false };
friend std::ostream& operator<<(std::ostream& os, fraction& ff);
struct get_sub_length;
private:
long long whole{ 0 };
long long decimal{ 0 };
};
#endif // rational_H
// definitions/source
struct get_sub_length {
size_t sub_len{};
size_t set_decimal_length(size_t& n) {
sub_len = n;
return sub_len;
}
size_t get_decimal_length() { return sub_len; }
}; get_sub_length slen;
struct coefficient {
std::vector<long long>coef;
}; coefficient C;
//compare's the value returned by convert with the original
// decimal value entered.
//if its within the tolarence of the epsilon consider it the best
//approximation you can get.
//feel free to experiment with the epsilon.
//for better results.
bool fraction::cmpf(long long& n1, long long& d1, const long double& epsilon = 0.0000005)
{
long double ex = pow(10, slen.get_decimal_length());
long long d = get_f_part(); // the original fractional part to use for comparison.
long double a = (long double)d / ex;
long double b = ((long double)d1 / (long double)n1);
if ((fabs(a - b) <= epsilon)) { return true; }
return false;
}
//Euclids algorithm returns the cofficients of a continued fraction through recursive division,
//for example: 0.375 -> 1/(375/1000) (note: for the fractional portion only).
// 1000/375 -> Remainder of 2.6666.... and 1000 -(2*375)=250,using only the integer value
// 375/250 -> Remainder of 1.5 and 375-(1*250)=125,
// 250/125 -> Remainder of 2.0 and 250-(2*125)=2
//the coefficients of the continued fraction are the integer values 2,1,2
// These are generally written [0;2,1,2] or [0;2,1,1,1] were 0 is the whole number value.
int fraction::Euclids_method(long long& n_dec, long long& exp)
{
long long quotient = 0;
if ((exp >= 1) && (n_dec != 0)) {
quotient = exp / n_dec;
C.coef.push_back(quotient);
long long divisor = n_dec;
long long dividend = exp - (quotient * n_dec);
Euclids_method(dividend, divisor); // recursive division
}
return 0;
}
// Convert is adding the elements stored in coef as a simple continued fraction
// which should result in a good approximation of the original decimal number.
void fraction::convert(std::vector<long long>& coef)
{
std::vector<long long>::iterator pos;
pos = C.coef.begin(), C.coef.end();
long long n1 = 0;
long long n2 = 1;
long long d1 = 1;
long long d2 = 0;
for_each(C.coef.begin(), C.coef.end(), [&](size_t pos) {
if (cmpf(n1, d1) == false) {
F.numerator = (n1 * pos) + n2;
n2 = n1;
n1 = F.numerator;
F.denominator = (d1 * pos) + d2;
d2 = d1;
d1 = F.denominator;
}
});
//flip the fraction back over to format the correct output.
F.numerator = d1;
F.denominator = n1;
}
// creates a fraction from the decimal component
// insures its in its abs form to ease calculations.
void fraction::make_fraction() {
size_t count = slen.get_decimal_length();
long long n_dec = decimal;
long long exp = (long long)pow(10, count);
Euclids_method(n_dec, exp);
convert(C.coef);
}
std::string get_w(const std::string& s)
{
std::string st = "0";
std::string::size_type pos;
pos = s.find(".");
if (pos - 1 == std::string::npos) {
st = "0";
return st;
}
else { st = s.substr(0, pos);
return st;
}
if (!(s.find("."))){
st = "0";
return st;
}
return st;
}
std::string get_d(const std::string& s)
{
std::string st = "0";
std::string::size_type pos;
pos = s.find(".");
if (pos == std::string::npos) {
st = "0";
return st;
}
std::string sub = s.substr(pos + 1);
st = sub;
size_t sub_len = sub.length();
slen.set_decimal_length(sub_len);
return st;
}
void fraction::ctf(double& nn)
{
//using stringstream for conversion to string
std::istringstream is;
is >> nn;
std::ostringstream os;
os << std::fixed << std::setprecision(14) << nn;
std::string s = os.str();
is_negative = false; //reset for loops
C.coef.erase(C.coef.begin(), C.coef.end()); //reset for loops
long double n = 0.0;
int m = 0;
//The whole number part will be seperated from the decimal part leaving a pure fraction.
//In such cases using Euclids agorithm would take the reciprocal 1/(n/exp) or exp/n.
//for pure continued fractions the cf must start with 0 + 1/(n+1/(n+...etc
//So the vector is initilized with zero as its first element.
C.coef.push_back(m);
std::cout << '\n';
if (s == "q") { // for loop structures
exit(0);
}
if (s.front() == '-') { // flag negative values.
is_negative = true; // represent nagative in output
s.erase(remove(s.begin(), s.end(), '-'), s.end()); // using abs
}
// w, d, seperate the string components
std::string w = get_w(s);
std::string d = get_d(s);
try
{
if (!(n = std::stold(s))) {throw invalid(); } // string_to_double()
get_fraction(w, d, n);
}
catch (std::exception& e) {
std::cout << e.what();
std::cout <<'\n'<< std::endl;
}
}
// The ostream formats and displays the various outputs
std::ostream& operator<<(std::ostream& os, fraction& f)
{
std::cout << '\n';
if (f.is_negative == true) {
os << "The coefficients are [" << '-' << f.whole << ";";
for (size_t i = 1; i < C.coef.size(); ++i) {
os << C.coef[i] << ',';
}
std::cout << "]" << '\n';
os << "The cf is: " << '-' << f.whole;
for (size_t i = 1; i < C.coef.size(); ++i) {
os << "+1/(" << C.coef[i];
}
for (size_t i = 1; i < C.coef.size(); ++i) {
os << ')';
}
std::cout << '\n';
if (F.value >= 1 && F.numerator == 0 && F.denominator == 1) {
F.numerator = abs(f.whole);
os << '-' << F.numerator << '/' << F.denominator << '\n';
return os;
}
else if (F.value == 0 && F.numerator == 0 && F.denominator == 1) {
os << F.numerator << '/' << F.denominator << '\n';
return os;
}
else if (F.value == 0 && F.numerator != 0 && F.denominator != 0) {
os << '-' << abs(F.numerator) << '/' << abs(F.denominator) << '\n';
return os;
}
else if (F.numerator == 0 && F.denominator == 0) {
os << '-' << f.whole << '\n';
return os;
}
else
os << '-' << (abs(f.whole) * abs(F.denominator) + abs(F.numerator)) << '/' << abs(F.denominator) << '\n';
}
if (f.is_negative == false) {
os << "The coefficients are [" << f.whole << ";";
for (size_t i = 1; i < C.coef.size(); ++i) {
os << C.coef[i] << ',';
}
std::cout << "]" << '\n';
os << "The cf is: " << f.whole;
for (size_t i = 1; i < C.coef.size(); ++i) {
os << "+1/(" << C.coef[i];
}
for (size_t i = 1; i < C.coef.size(); ++i) {
os << ')';
}
std::cout << '\n';
if (F.value >= 1 && F.numerator == 0 && F.denominator == 1) {
F.numerator = abs(f.whole);
os << F.numerator << '/' << F.denominator << '\n';
return os;
}
else if (F.value == 0 && F.numerator != 0 && F.denominator != 0) {
os << abs(F.numerator) << '/' << abs(F.denominator) << '\n';
return os;
}
else if (F.numerator == 0 && F.denominator == 0) {
os << f.whole << '\n';
return os;
}
else
os << (abs(f.whole) * abs(F.denominator) + abs(F.numerator)) << '/' << abs(F.denominator) << '\n';
os << f.whole << ' ' << F.numerator << '/' << F.denominator << '\n';
}
return os;
}
int main()
{
fraction f;
double s = 0;
std::cout << "Enter a number to convert to a fraction\n";
std::cout << "Enter a \"q\" to quit\n";
// uncomment for a loop
while (std::cin >> s) {
f.ctf(s);
std::cout << f << std::endl;
}
// comment out these lines if you want the loop
//std::cin >> s;
//f.ctf(s);
//std::cout << f << std::endl;
}