Difference between x * 0.1 and x / 10? - c++

I am a high school student and I saw a while ago that is better to multiply than to divide. Since then, without any proof found that it is true or not and without knowing how to do find it by myself at the moment, I tried to modify my codes for that slightly better time.
Here is a problem where I wanted to find the biggest digit in a number using recursion.
This one is working.
#include <iostream>
using namespace std;
int minn = 9;
int digit(int n)
{
if(minn > n % 10)
minn = n % 10;
if(!(n / 10))
return minn;
else
return digit(n / 10);
}
int main()
{
int x;
cin >> x;
cout << digit(x);
return 0;
}
But this is not working.
#include <iostream>
using namespace std;
int minn = 9;
int digit(int n)
{
if(minn > n % 10)
minn = n % 10;
if(!(n * 0.1))
return minn;
else
return digit(n / 10);
}
int main()
{
int x;
cin >> x;
cout << digit(x);
return 0;
}
The only difference is that the broken one use if(!(n * 0.1)) not if(!(n / 10)).
Can someone clarify it for me or anyone who is seeking help what is the difference between x * 0.1 and x / 10?
Thank you all for clicking the question and that you tried to help!

0.1 is a double type, 10 is an integer type.
When dividing two integers e.g. n / 10 you will get integer division (e.g. 6/10 will equal 0).
And your check will work differently when using 6 * 0.1 as that will equal 0.6.

n * .1 results in a floating point result. So, 3 * .1 produces the result of .3, which is definitely not 0.
On the other hand, 3/10 is 0. That's how integer division works in C++.

You define x as int, x*0.1 uses float arithmetics, while x/10 uses integer arithmetics

Can someone clarify it for me or anyone who is seeking help what is the difference between x * 0.1 and x / 10?
Difference is very significant. In the first case you use floating point multiplication in the second integer division. So first if() would happen when n == 0 while second when n < 10.
if( !(n*0.1) ) // for if to work result of n * 0.1 must be equal 0 which only happens when n == 0
if( !(n/10) ) // for if to work result of n / 10 must be equal to 0 which happens when abs(n) < 10 (including 0)

Related

why floating point numbers does not give desired answer?

hey I am making small C++ program to calculate the value of sin(x) till 7 decimal points but when I calculate sin(PI/2) using this program it gives me 0.9999997 rather than 1.0000000 how can I solve this error?
I know of little bit why I'm getting this value as output, question is what should be my approach to solve this logical error?
here is my code for reference
#include <iostream>
#include <iomanip>
#define PI 3.1415926535897932384626433832795
using namespace std;
double sin(double x);
int factorial(int n);
double Pow(double a, int b);
int main()
{
double x = PI / 2;
cout << setprecision(7)<< sin(x);
return 0;
}
double sin(double x)
{
int n = 1; //counter for odd powers.
double Sum = 0; // to store every individual expression.
double t = 1; // temp variable to store individual expression
for ( n = 1; t > 10e-7; Sum += t, n = n + 2)
{
// here i have calculated two terms at a time because addition of two consecutive terms is always less than 1.
t = (Pow(-1.00, n + 1) * Pow(x, (2 * n) - 1) / factorial((2 * n) - 1))
+
(Pow(-1.00, n + 2) * Pow(x, (2 * (n+1)) - 1) / factorial((2 * (n+1)) - 1));
}
return Sum;
}
int factorial(int n)
{
if (n < 2)
{
return 1;
}
else
{
return n * factorial(n - 1);
}
}
double Pow(double a, int b)
{
if (b == 1)
{
return a;
}
else
{
return a * Pow(a, b - 1);
}
}
sin(PI/2) ... it gives me 0.9999997 rather than 1.0000000
For values outside [-pi/4...+pi/4] the Taylor's sin/cos series converges slowly and suffers from cancelations of terms and overflow of int factorial(int n)**. Stay in the sweet range.
Consider using trig properties sin(x + pi/2) = cos(x), sin(x + pi) = -sin(x), etc. to bring x in to the [-pi/4...+pi/4] range.
Code uses remquo (ref2) to find the remainder and part of quotient.
// Bring x into the -pi/4 ... pi/4 range (i.e. +/- 45 degrees)
// and then call owns own sin/cos function.
double my_wide_range_sin(double x) {
if (x < 0.0) {
return -my_sin(-x);
}
int quo;
double x90 = remquo(fabs(x), pi/2, &quo);
switch (quo % 4) {
case 0:
return sin_sweet_range(x90);
case 1:
return cos_sweet_range(x90);
case 2:
return sin_sweet_range(-x90);
case 3:
return -cos_sweet_range(x90);
}
return 0.0;
}
This implies OP needs to code up a cos() function too.
** Could use long long instead of int to marginally extend the useful range of int factorial(int n) but that only adds a few x. Could use double.
A better approach would not use factorial() at all, but scale each successive term by 1.0/(n * (n+1)) or the like.
I see three bugs:
10e-7 is 10*10^(-7) which seems to be 10 times larger than you want. I think you wanted 1e-7.
Your test t > 10e-7 will become false, and exit the loop, if t is still large but negative. You may want abs(t) > 1e-7.
To get the desired accuracy, you need to get up to n = 7, which has you computing factorial(13), which overflows a 32-bit int. (If using gcc you can catch this with -fsanitize=undefined or -ftrapv.) You can gain some breathing room by using long long int which is at least 64 bits, or int64_t.

How to fix "PI recursive function" code to work with all values of n?

I'm working on a code that calculates PI with n terms. However, my code only works correctly with some values of n.
This piece of code even numbers do not work and when I switch up the negative sign the odd numbers do not work.
double PI(int n, double y=2){
double sum = 0;
if (n==0){
return 3;
}else if (n % 2 != 0){
sum = (4/(y*(y+1)*(y+2)))+(PI (n - 1 ,y+2)) ;
}else{
sum= -(4/(y*(y+1)*(y+2)))+PI (n - 1,y+2) ;
}
return sum;
}
int main(int argc, const char * argv[]) {
double n = PI (2,2);
cout << n << endl;
}
For n = 2 I expected a result of 3.1333 but I got a value of 2.86667
This is the formula for calculating PI , y is the denominator and n is the number of terms
Firstly, I will assume that a complete runnable case of your code looks like
#include <iostream>
using namespace std;
double PI(int n, double y=2){
double sum = 0;
if (n==0){
return 3;
}else if (n % 2 != 0){
sum = (4/(y*(y+1)*(y+2)))+(PI (n - 1 ,y+2)) ;
}else{
sum= -(4/(y*(y+1)*(y+2)))+PI (n - 1,y+2) ;
}
return sum;
}
int main(int argc, const char * argv[]) {
double n = PI (2,2);
cout << n << endl;
}
I believe that you are attempting to compute pi through the formula
(pi - 3)/4 = \sum_{k = 1}^{\infty} (-1)^{k+1} / ((2k(2k+1)(2k+2)),
(where here and elsewhere I use LaTeX code to represent mathy things). This is a good formula that converges pretty quickly despite being so simple. If you were to use the first two terms of the sum, you would find that
(pi - 3)/4 \approx 1/(2*3*4) - 1/(4*5*6) ==> pi \approx 3.13333,
which you seem to indicate in your question.
To see what's wrong, you might trace through your first function call with PI(2, 2). This produces three terms.
n=2: 2 % 2 == 0, so the first term is -4/(2*3*4) + PI(1, 4). This is the wrong sign.
n=1: 1 % 2 == 1, so the second term is 4/(4*5*6), which is also the wrong sign.
n=0: n == 0, so the third term is 3, which is the correct sign.
So you have computed
3 - 4/(2*3*4) + 4/(4*5*6)
and we can see that there are many sign errors.
The underlying reason is because you are determining the sign based on n, but if you examine the formula the sign depends on y. Or in particular, it depends on whether y/2 is odd or even (in your formulation, where you are apparently only going to provide even y values to your sum).
You should change y and n appropriately. Or you might recognize that there is no reason to decouple them, and use something like the following code. In this code, n represents the number of terms to use and we compute y accordingly.
#include <iostream>
using namespace std;
double updatedPI(int n)
{
int y = 2*n;
if (n == 0) { return 3; }
else if (n % 2 == 1)
{
return 4. / (y*(y + 1)*(y + 2)) + updatedPI(n-1);
}
else
{
return -4. / (y*(y + 1)*(y + 2)) + updatedPI(n-1);
}
}
int main() {
double n = updatedPI(3);
cout << n << endl;
}
The only problem with your code is that y is calculated incorrectly. It has to be equal to 2 * n. Simply modifying your code that way gives correct results:
Live demo: https://wandbox.org/permlink/3pZNYZYbtHm7k1ND
That is, get rid of the y function parameter and set int y = 2 * n; in your function.

Floating point error in C++ code

I am trying to solve a question in which i need to find out the number of possible ways to make a team of two members.(note: a team can have at most two person)
After making this code, It works properly but in some test cases it shows floating point error ad i can't find out what it is exactly.
Input: 1st line : Number of test cases
2nd line: number of total person
Thank you
#include<iostream>
using namespace std;
long C(long n, long r)
{
long f[n + 1];
f[0] = 1;
for (long i = 1; i <= n; i++)
{
f[i] = i * f[i - 1];
}
return f[n] / f[r] / f[n - r];
}
int main()
{
long n, r, m,t;
cin>>t;
while(t--)
{
cin>>n;
r=1;
cout<<C(n, min(r, n - r))+1<<endl;
}
return 0;
}
You aren't getting a floating point exception. You are getting a divide by zero exception. Because your code is attempting to divide by the number 0 (which can't be done on a computer).
When you invoke C(100, 1) the main loop that initializes the f array inside C increases exponentially. Eventually, two values are multiplied such that i * f[i-1] is zero due to overflow. That leads to all the subsequent f[i] values being initialized to zero. And then the division that follows the loop is a division by zero.
Although purists on these forums will say this is undefined, here's what's really happening on most 2's complement architectures. Or at least on my computer....
At i==21:
f[20] is already equal to 2432902008176640000
21 * 2432902008176640000 overflows for 64-bit signed, and will typically become -4249290049419214848 So at this point, your program is bugged and is now in undefined behavior.
At i==66
f[65] is equal to 0x8000000000000000. So 66 * f[65] gets calculated as zero for reasons that make sense to me, but should be understood as undefined behavior.
With f[66] assigned to 0, all subsequent assignments of f[i] become zero as well. After the main loop inside C is over, the f[n-r] is zero. Hence, divide by zero error.
Update
I went back and reverse engineered your problem. It seems like your C function is just trying to compute this expression:
N!
-------------
R! * (N-R)!
Which is the "number of unique sorted combinations"
In which case instead of computing the large factorial of N!, we can reduce that expression to this:
n
[ ∏ i ]
n-r
--------------------
R!
This won't eliminate overflow, but will allow your C function to be able to take on larger values of N and R to compute the number of combinations without error.
But we can also take advantage of simple reduction before trying to do a big long factorial expression
For example, let's say we were trying to compute C(15,5). Mathematically that is:
15!
--------
10! 5!
Or as we expressed above:
1*2*3*4*5*6*7*8*9*10*11*12*13*14*15
-----------------------------------
1*2*3*4*5*6*7*8*9*10 * 1*2*3*4*5
The first 10 factors of the numerator and denominator cancel each other out:
11*12*13*14*15
-----------------------------------
1*2*3*4*5
But intuitively, you can see that "12" in the numerator is already evenly divisible by denominators 2 and 3. And that 15 in the numerator is evenly divisible by 5 in the denominator. So simple reduction can be applied:
11*2*13*14*3
-----------------------------------
1 * 4
There's even more room for greatest common divisor reduction, but this is a great start.
Let's start with a helper function that computes the product of all the values in a list.
long long multiply_vector(std::vector<int>& values)
{
long long result = 1;
for (long i : values)
{
result = result * i;
if (result < 0)
{
std::cout << "ERROR - multiply_range hit overflow" << std::endl;
return 0;
}
}
return result;
}
Not let's implement C as using the above function after doing the reduction operation
long long C(int n, int r)
{
if ((r >= n) || (n < 0) || (r < 0))
{
std::cout << "invalid parameters passed to C" << std::endl;
return 0;
}
// compute
// n!
// -------------
// r! * (n-r)!
//
// assume (r < n)
// Which maps to
// n
// [∏ i]
// n - r
// --------------------
// R!
int end = n;
int start = n - r + 1;
std::vector<int> numerators;
std::vector<int> denominators;
long long numerator = 1;
long long denominator = 1;
for (int i = start; i <= end; i++)
{
numerators.push_back(i);
}
for (int i = 2; i <= r; i++)
{
denominators.push_back(i);
}
size_t n_length = numerators.size();
size_t d_length = denominators.size();
for (size_t n = 0; n < n_length; n++)
{
int nval = numerators[n];
for (size_t d = 0; d < d_length; d++)
{
int dval = denominators[d];
if ((nval % dval) == 0)
{
denominators[d] = 1;
numerators[n] = nval / dval;
}
}
}
numerator = multiply_vector(numerators);
denominator = multiply_vector(denominators);
if ((numerator == 0) || (denominator == 0))
{
std::cout << "Giving up. Can't resolve overflow" << std::endl;
return 0;
}
long long result = numerator / denominator;
return result;
}
You are not using floating-point. And you seem to be using variable sized arrays, which is a C feature and possibly a C++ extension but not standard.
Anyway, you will get overflow and therefore undefined behaviour even for rather small values of n.
In practice the overflow will lead to array elements becoming zero for not much larger values of n.
Your code will then divide by zero and crash.
They also might have a test case like (1000000000, 999999999) which is trivial to solve, but not for your code which I bet will crash.
You don't specify what you mean by "floating point error" - I reckon you are referring to the fact that you are doing an integer division rather than a floating point one so that you will always get integers rather than floats.
int a, b;
a = 7;
b = 2;
std::cout << a / b << std::endl;
this will result in 3, not 3.5! If you want floating point result you should use floats instead like this:
float a, b;
a = 7;
b = 2;
std::cout << a / b << std::end;
So the solution to your problem would simply be to use float instead of long long int.
Note also that you are using variable sized arrays which won't work in C++ - why not use std::vector instead??
Array syntax as:
type name[size]
Note: size must a constant not a variable
Example #1:
int name[10];
Example #2:
const int asize = 10;
int name[asize];

Calculating a Sum with C++

I wrote the following code to sum the series (-1)^i*(i/(i+1)). But when I run it I get -1 for any value of n.
Can some one please point out what I am doing wrong? Thank you in advance!
#include <iostream>
using namespace std;
int main()
{
int sum = 0;
int i = 1.0;
int n = 5.0;
for(i=1;i<=n;i++)
sum = (-1)^i*(i/(i+1));
cout << "Sum" <<" = "<< sum << endl;
return 0;
}
Problem #1: The C++ ^ operator isn't the math power operator. It's a bitwise XOR.
You should use pow() instead.
Problem #2:
You are storing floating-point types into an integer type. So the following will result in integer division (truncated division):
i/(i+1)
Problem #3:
You are not actually summing anything up:
sum = ...
should be:
sum += ...
A corrected version of the code is as follows:
double sum = 0;
int i = 1;
int n = 5;
for(i = 1; i <= n; i++)
sum += pow(-1.,(double)i) * ((double)i / (i + 1));
Although you really don't need to use pow in this case. A simple test for odd/even will do.
double sum = 0;
int i = 1;
int n = 5;
for(i = 1; i <= n; i++){
double val = (double)i / (i + 1);
if (i % 2 != 0){
val *= -1.;
}
sum += val;
}
You need too put sum += pow(-1,i)*(i/(i+1));
Otherwise you lose previous result each time.
Use pow function for pow operation.
edit : as said in other post, use double or float instead of int to avoid truncated division.
How about this
((i % 2) == 0 ? 1 : -1)
instead of
std::pow(-1, i)
?
Full answer:
double sum = 0;
int i = 1.0;
int n = 5.0;
for (i = 1; i <= n; ++i) {
signed char sign = ((i % 2) == 0 ? 1 : -1);
sum += sign * (i / (i+1));
}
Few problems:
^ is teh bitwise exclusive or in c++ not "raised to power". Use pow() method.
Remove the dangling opening bracket from the last line
Use ints not floats when assigning to ints.
You seem to have a few things wrong with your code:
using namespace std;
This is not directly related to your problem at hand, but don't ever say using namespace std; It introduces subtle bugs.
int i = 1.0;
int n = 5.0;
You are initializaing integral variables with floating-point constants. Try
int i = 1;
int n = 5;
sum = (-1)^i*(i/(i+1));
You have two problems with this expression. First, the quantity (i/(i+1)) is always zero. Remember dividing two ints rounds the result. Second, ^ doesn't do what you think it does. It is the exclusive-or operator, not the exponentiation operator. Third, ^ binds less tightly than *, so your expression is:
-1 xor (i * (i/(i+1)))
-1 xor (i * 0)
-1 xor 0
-1
^ does not do what you think it does. Also there are some other mistakes in your code.
What it should be:
#include <iostream>
#include <cmath>
int main( )
{
long sum = 0;
int i = 1;
int n = 5;
for( i = 1; i <= n; i++ )
sum += std::pow( -1.f, i ) * ( i / ( i + 1 ) );
std::cout << "Sum = " << sum << std::endl;
return 0;
}
To take a power of a value, use std::pow (see here). Also you can not assign int to a decimal value. For that you need to use float or double.
The aforementioned ^ is a bitwise-XOR, not a mark for an exponent.
Also be careful of Integer Arithmetic as you may get unexpected results. You most likely want to change your variables to either float or double.
There are a few issues with the code:
int sum = 0;
The intermediate results are not integers, this should be a double
int i = 1.0;
Since you will use this in a division, it should be a double, 1/2 is 0 if calculated in integers.
int n = 5.0;
This is an int, not a floating point value, no .0 is needed.
for(i=1;i<=n;i++)
You've already initialized i to 1, why do it again?
sum = (-1)^i*(i/(i+1));
Every iteration you lose the previous value, you should use sum+= 'new values'
Also, you don't need pow to calculate (-1)^i, all this does is switch between +1 and -1 depending on the odd/even status of i. You can do this easier with an if statement or with 2 for's, one for odd i one for even ones... Many choices really.

Calculating the value of pi-what is wrong with my code

I'm doing another C++ exercise. I have to calculate the value of pi from the infinite series:
pi=4 - 4/3 + 4/5 – 4/7 + 4/9 -4/11+ . . .
The program has to print the approximate value of pi after each of the first 1,000 terms of this series.
Here is my code:
#include <iostream>
using namespace std;
int main()
{
double pi=0.0;
int counter=1;
for (int i=1;;i+=2)//infinite loop, should "break" when pi=3.14159
{
double a=4.0;
double b=0.0;
b=a/static_cast<double>(i);
if(counter%2==0)
pi-=b;
else
pi+=b;
if(i%1000==0)//should print pi value after 1000 terms,but it doesn't
cout<<pi<<endl;
if(pi==3.14159)//this if statement doesn't work as well
break;
counter++;
}
return 0;
}
It compiles without errors and warnings, but only the empty console window appears after execution. If I remove line” if(i%1000==0)” , I can see it does run and print every pi value, but it doesn’t stop, which means the second if statement doesn’t work either. I’m not sure what else to do. I’m assuming it is probably a simple logical error.
Well, i % 1000 will never = 0, as your counter runs from i = 1, then in increments of 2. Hence, i is always odd, and will never be a multiple of 1000.
The reason it never terminates is that the algorithm doesn't converge to exactly 3.14157 - it'll be a higher precision either under or over approximation. You want to say "When within a given delta of 3.14157", so write
if (fabs(pi - 3.14157) < 0.001)
break
or something similar, for however "close" you want to get before you stop.
Since you start i at 1 and increment by 2, i is always an odd number, so i % 1000 will never be 0.
you have more than one problem:
A. i%1000==0 will never be true because you're iterating only odd numbers.
B. pi==3.14159 : you cannot compare double values just like that because the way floating point numbers are represented (you can read about it here in another question). in order for it to work you should compare the values in another way - one way is to subtract them from each other and check that the absolute result is lower than 0.0000001.
You have floating point precision issues. Try if(abs(pi - 3.14159) < 0.000005).
i%1000 will never be 0 because i is always odd.
Shouldn't it be:
if (counter%1000==0)
i starts at 1 and then increments by 2. Therefore i is always odd and will never be a multiple of 1000, which is why if (i % 1000 == 0) never passes.
Directly comparing floats doesn't work, due to floating precision issues. You will need to compare that the difference between the values is close enough.
pi=4 - 4/3 + 4/5 – 4/7 + 4/9 -4/11 + ...
Generalising
pi = Σi=0∞ (-1)i 4 / (2i+1)
Which gives us a cleaner approach to each term; the i'th term is given by:
double term = pow(-1,i%2) * 4 / (2*i+1);
where i=0,1,2,...,N
So, our loop can be fairly simple, given some number of iterations N
int N=2000;
double pi=0;
for(int i=0; i<N; i++)
{
double term = pow(-1,i%2) * 4 / (2*(double)i+1);
pi += term;
cout << i << "\t" << pi <<endl;
}
Your original question stated "The program has to print the approximate value of pi after each of the first 1,000 terms of this series". This does not imply any need to check whether 3.14159 has been reached, so I have not included this here. The pow(-1,i%2) call is just to avoid if statements (which are slow) and prevent any complications with large i.
Be aware that after a number of iterations, the difference between the magnitude of pi and the magnitude of the correcting term (say -4/25) will be so small that it will go beyond the precision of a double, so you would need higher precision types to deal with it.
By default abs uses the abs macro which is for int. For doubles, use the cmath library.
#include <iostream>
#include <cmath>
int main()
{
double pi=0.0;
double a=4.0;
int i = 1;
for (i=1;;i+=2)
{
pi += (1 - 2 * ((i/2)%2)) * a/static_cast<double>(i);
if( std::abs(pi - 3.14159) < 0.000001 )
break;
if (i > 2000) //1k iterations
break;
}
std::cout<<pi<<std::endl;
return 0;
}
Here is the corrected code. I thought it may be helpful in the future if somebody has similar problem.
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
double pi=0.0;
int counter=1;
for (int i=1;;i+=2)
{
double a=4.0;
double b=0.0;
b=a/static_cast<double>(i);
if(counter%2==0)
pi-=b;
else
pi+=b;
if(counter%1000==0)
cout<<pi<<" "<<counter<<endl;
if (fabs(pi - 3.14159) < 0.000001)
break;
counter++;
}
cout<<pi;
return 0;
}
Here is a better one:
class pi_1000
{
public:
double doLeibniz( int i ) // Leibniz famous formula for pi, source: Calculus II :)
{
return ( ( pow( -1, i ) ) * 4 ) / ( ( 2 * i ) + 1 );
}
void piCalc()
{
double pi = 4;
int i;
cout << "\npi calculated each iteration from 1 to 1000\n"; //wording was a bit confusing.
//I wasn't sure which one is the right one: 0-1000 or each 1000th.
for( i = 1; i < 1000; i++ )
{
pi = pi + doLeibniz( i );
cout << fixed << setprecision( 5 ) << pi << "\t" << i + 1 << "\n";
}
pi = 4;
cout << "\npi calculated each 1000th iteration from 1 to 20000\n";
for( i = 1; i < 21000; i++ )
{
pi = pi + doLeibniz( i );
if( ( ( i - 1 ) % 1000 ) == 0 )
cout << fixed << setprecision( 5 ) << pi << "\t" << i - 1 << "\n";
}
}