How to check if 1/a == 1/b + 1/c in c++? - c++

I'm trying to check if 1/a == 1/b + 1/c in c++.
a, b and c are positive integers and a is between 1 and 10000.
I'm currently getting wrong answers due to floating point precision and I cannot find a way to do this comparison without using floats.
How do I get a correct answer?

I think this will help you:
1/a = 1/b + 1/c
1 = a/b + a/c
1 = (ac + ab)/bc
bc = ac + ab #no longer needs division

Multiply both sides of the equation by a*b*c to get
b*c == a*c + a*b

a(b+c)==b*c
should work just fine :)

When comparing floating point values it's often not practical to look for exact matches because of precision issues. They can foil even the simplest of problems.
double d = sqrt(2);
cout << (d * d) == 2 // false
Instead you often have to test to see if the values are within a certain error margin
fabs((d * d) - 2) < .001 // true

As this is a programming question, I assume you mean int division.
Now, 1/a where a is a positive intteger type is either 0 or 1, and in fact is 1 iff a==1.
We can abuse bool casts as follows:
(a==1) == ((b==1)+(c==1))
and we avoid any and all use of floats.

You could always turn this into a class called fraction. Use the common denominator to convert all 3 variables to the same denominator, add b and c, then compare to a.

Related

Simplest Way of Rounding Up the Average in C++

int a, b, c = 0;
c = (a+b)/2;
In this code, if both "a" and "b" are even (Example 1), then there's no problem. But if one of them is odd (Example 2), then the answer will have +0.5. I want to round it up.
Example 1.
a=4, b=10
c will be = 7 This is OK.
Example 2.
a=3, b=4
c will be = 3.5
And I want c to be rounded up and become 4 instead.
First off, you're wrong. c is an integer, so it can't be 3.5. Furthermore, a, b and 2 are all integers, so the division is integer division, so it can't result in 3.5 either. It will be rounded towards zero, so it will be 3.
That said, to get integer division by 2 to round up instead of down, simply add 1 before dividing. (14 + 1) / 2 == 7, so that's still right. (7 + 1) / 2 == 4, so that's correct too.
Use the ceil function. It will always round up whatever number you put in it.
First of all, make c a double, then use
c = (a + b)/2.0
otherwise you have truncation due to division of ints being casted to int. In this way, (a + b) / 2.0 is a double, due to the denominator being a double, so you don't have any truncation.
Next, use the function std::round from C++11, or std::floor/std::ceil, depending on what exactly you want
Alternatively, you can keep c and int but do
c = std::round( (a + b) / 2.0 ); // rounding to nearest integer, C++11
or
c = std::floor( (a + b) / 2.0 ); // rounding down
or
c = std::ceil( (a + b) / 2.0 ); // rounding up
If you don't want any warnings, can also explicitly cast the result of std::floor/std::ceil/std::round back to int, like
c = static_cast<int>(std::round( (a + b) / 2.0 )); // now we tell the compiler we know what we're doing
int a, b, c = 0;
c = (a+b+1)/2;
The simplest thing is to use the ceil() function from <math.h>.
int a, b, c = 0;
c = (int) ceil((float)(a+b)/2);
The easiest thing would be to use + 1 after the result if the result is not round (what the ceil function would do by default for you)
int a, b, c = 0;
if ((a + b) % 2 == 1)
c = ((a+b)/2) + 1;
else
c = (a+b)/2;
Demo: https://ideone.com/AmgDUt

Fast integer solution of x(x-1)/2 = c

Given a non-negative integer c, I need an efficient algorithm to find the largest integer x such that
x*(x-1)/2 <= c
Equivalently, I need an efficient and reliably accurate algorithm to compute:
x = floor((1 + sqrt(1 + 8*c))/2) (1)
For the sake of defineteness I tagged this question C++, so the answer should be a function written in that language. You can assume that c is an unsigned 32 bit int.
Also, if you can prove that (1) (or an equivalent expression involving floating-point arithmetic) always gives the right result, that's a valid answer too, since floating-point on modern processors can be faster than integer algorithms.
If you're willing to assume IEEE doubles with correct rounding for all operations including square root, then the expression that you wrote (plus a cast to double) gives the right answer on all inputs.
Here's an informal proof. Since c is a 32-bit unsigned integer being converted to a floating-point type with a 53-bit significand, 1 + 8*(double)c is exact, and sqrt(1 + 8*(double)c) is correctly rounded. 1 + sqrt(1 + 8*(double)c) is accurate to within one ulp, since the last term being less than 2**((32 + 3)/2) = 2**17.5 implies that the unit in the last place of the latter term is less than 1, and thus (1 + sqrt(1 + 8*(double)c))/2 is accurate to within one ulp, since division by 2 is exact.
The last piece of business is the floor. The problem cases here are when (1 + sqrt(1 + 8*(double)c))/2 is rounded up to an integer. This happens if and only if sqrt(...) rounds up to an odd integer. Since the argument of sqrt is an integer, the worst cases look like sqrt(z**2 - 1) for positive odd integers z, and we bound
z - sqrt(z**2 - 1) = z * (1 - sqrt(1 - 1/z**2)) >= 1/(2*z)
by Taylor expansion. Since z is less than 2**17.5, the gap to the nearest integer is at least 1/2**18.5 on a result of magnitude less than 2**17.5, which means that this error cannot result from a correctly rounded sqrt.
Adopting Yakk's simplification, we can write
(uint32_t)(0.5 + sqrt(0.25 + 2.0*c))
without further checking.
If we start with the quadratic formula, we quickly reach sqrt(1/4 + 2c), round up at 1/2 or higher.
Now, if you do that calculation in floating point, there can be inaccuracies.
There are two approaches to deal with these inaccuracies. The first would be to carefully determine how big they are, determine if the calculated value is close enough to a half for them to be important. If they aren't important, simply return the value. If they are, we can still bound the answer to being one of two values. Test those two values in integer math, and return.
However, we can do away with that careful bit, and note that sqrt(1/4 + 2c) is going to have an error less than 0.5 if the values are 32 bits, and we use doubles. (We cannot make this guarantee with floats, as by 2^31 the float cannot handle +0.5 without rounding).
In essense, we use the quadratic formula to reduce it to two possibilities, and then test those two.
uint64_t eval(uint64_t x) {
return x*(x-1)/2;
}
unsigned solve(unsigned c) {
double test = sqrt( 0.25 + 2.*c );
if ( eval(test+1.) <= c )
return test+1.
ASSERT( eval(test) <= c );
return test;
}
Note that converting a positive double to an integral type rounds towards 0. You can insert floors if you want.
This may be a bit tangential to your question. But, what caught my attention is the specific formula. You are trying to find the triangular root of Tn - 1 (where Tn is the nth triangular number).
I.e.:
Tn = n * (n + 1) / 2
and
Tn - n = Tn - 1 = n * (n - 1) / 2
From the nifty trick described here, for Tn we have:
n = int(sqrt(2 * c))
Looking for n such that Tn - 1 ≤ c in this case doesn't change the definition of n, for the same reason as in the original question.
Computationally, this saves a few operations, so it's theoretically faster than the exact solution (1). In reality, it's probably about the same.
Neither this solution or the one presented by David are as "exact" as your (1) though.
floor((1 + sqrt(1 + 8*c))/2) (blue) vs int(sqrt(2 * c)) (red) vs Exact (white line)
floor((1 + sqrt(1 + 8*c))/2) (blue) vs int(sqrt(0.25 + 2 * c) + 0.5 (red) vs Exact (white line)
My real point is that triangular numbers are a fun set of numbers that are connected to squares, pascal's triangle, Fibonacci numbers, et. al.
As such there are loads of identities around them which might be used to rearrange the problem in a way that didn't require a square root.
Of particular interest may be that Tn + Tn - 1 = n2
I'm assuming you know that you're working with a triangular number, but if you didn't realize that, searching for triangular roots yields a few questions such as this one which are along the same topic.

addition instead of subtraction in Kahan algorithm

This is the Kahan summation algorithm from Wikipedia:
function KahanSum(input)
var sum = 0.0
var c = 0.0
for i = 1 to input.length do
y = input[i] - c // why subtraction?
t = sum + y
c = (t - sum) - y
sum = t
return sum
Is there a specific reason why it uses subtraction (as opposed to addition)? If I swap the operands in the computation of c, can I use addition instead? Somehow, that would make more sense to me:
function KahanSum(input)
var sum = 0.0
var c = 0.0
for i = 1 to input.length do
y = input[i] + c // addition instead of subtraction
t = sum + y
c = y - (t - sum) // swapped operands
sum = t
return sum
Or is there some weird difference between floating point addition and subtraction I don't know about yet?
Also, is there any difference between (t - sum) - y and t - sum - y in the original algorithm? Aren't the parenthesis redundant, since - is left-associative, anyway?
As far as I can tell, your method is exactly equivalent to the one from Wikipedia. The only difference is that the sign of c -- and therefore its meaning -- is reversed. In the Wikipedia algorithm, c is the "wrong" part of the sum; c=0.0001 means that the sum is a little bigger than it should be. In your version, c is the "correction" to the sum; c=-0.0001 means that the sum should be made a little smaller.
And I think the parentheses are for readability. They're for us, not the machine.
Your two algorithms are equivalent. The only difference during execution will be the sign of c. The reason it uses addition is because in Kahan's version, c represents the error, which is conventionally the correct minus the computed value.
In the sense that parentheses specify the order of operations, the parentheses are absolutely necessary. In fact, they are what makes this algorithm work!
When subtraction is left-associative, as it is in most languages, a - b - c evaluates as (a - b) - c so the two are the same. But the subtraction in the Kahan algorithm is a - (b - c), and that should not be evaluated as a - b + c.
Floating-point addition and subtraction are not associative. For expressions that are equivalent in standard arithmetic, you may get different results depending on the order in which you perform the operations.
Let's work with 3 decimal digits of precision, for the sake of clarity. This means that if we get a result with 4 digits, we have to round it.
Now compare (a - b) - c with the mathematically equivalent a - (b + c) for some specific values:
(998 - 997) - 5 = 1 - 5 = -4
with
998 - (997 + 5) = 998 - Round(1002)
= 998 - 1000 = -2
So the second approach is less accurate.
In the Kahan algorithm, t and sum will usually be relatively large compared to y. So you often get a situation like in the example above where you would get a less accurate result if you don't do the operations in the correct order.

Can float values add to a sum of zero? [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Most effective way for float and double comparison
I have two values(floats) I am attempting to add together and average. The issue I have is that occasionally these values would add up to zero, thus not requiring them to be averaged.
The situation I am in specifically contains the values "-1" and "1", yet when added together I am given the value "-1.19209e-007" which is clearly not 0. Any information on this?
I'm sorry but this doesn't make sense to me.
Two floating point values, if they are exactly the same but with opposite sign, subtracted will produce always 0. This is how floating point operations works.
float a = 0.2f;
float b = -0.2f;
float f = (a - b) / 2;
printf("%f %d\n", f, f != 0); // will print out 0.0000 0
Will be always 0 also if the compiler doesn't optimize the code.
There is not any kind of rounding error to take in account if a and b have the same value but opposite sign! That is, if the higher bit of a is 0 and the higher bit of b is 1 and all other bits are the same, the result cannot be other than 0.
But if a and b are slightly different, of course, the result can be non-zero.
One possible solution to avoid this can be using a tolerance...
float f = (a + b) / 2;
if (abs(f) < 0.000001f)
f = 0;
We are using a simple tolerance to see if our value is near to zero.
A nice example code to show this is...
int main(int argc)
{
for (int i = -10000000; i <= 10000000 * argc; ++i)
{
if (i != 0)
{
float a = 3.14159265f / i;
float b = -a + (argc - 1);
float f = (a + b) / 2;
if (f != 0)
printf("%f %d\n", a, f);
}
}
printf("completed\n");
return 0;
}
I'm using "argc" here as a trick to force the compiler to not optimize out our code.
At least right off, this sounds like typical floating point imprecision.
The usual way to deal with it is to round your numbers to the correct number of significant digits. In this case, your average would be -1.19209e-08 (i.e., 0.00000001192). To (say) six or seven significant digits, that is zero.
Takes the sum of all your numbers, divide by your count. Round off your answer to something reasonable before you do prints, reports comparisons, or whatever you're doing.
again, do some searching on this but here is the basic explanation ...
the computer approximates floating point numbers by base 2 instead of base 10. this means that , for example, 0.2 (when converted to binary) is actually 0.001100110011 ... on forever. since the computer cannot add these on forever, it must approximate it.
because of these approximations, we lose "precision" of calculations. hence "single" and "double" precision floating point numbers. this is why you never test for a float to be actually 0. instead, you test whether is below some threshhold which you want to use as zero.

Differentiate between a number (of type double) with decimal places and one without - c++

I am trying to implement a simple decimation algorithm in c++. I have two arrays, say p & q, where the subscripts are related to each other by the following relation:
p[k] = q[0.5*k]. This means that the following sequence should hold valid:
p[0] = q[0]
p[1] = 0
p[2] = q[1]
p[3] = 0
p[4] = q[2]
and so on...
Please note that p[k] takes on a value only and only when the result of (0.5*k) contains no decimal places (or has 0 in decimal) and does not use any rounding off etc.
My question is: Is there a way to distinguish between an integer (a number with no decimal places or only 0 in decimal, say 2.0) and a number with decimal places in C++, provided both are cast to double?
eg.) 2.0 is an integer cast to double. 2.1 is a number with decimal places.
eg. 2) * 0.9*2 should put 0 into array p while 0.9*10 should put q[9] into array p.*
If I use the statement, (int) (0.5*k), then I end up with an integer in every case, irrespective of the value of k.
Edit: The 0.5 in the above case is only illustrative. It could be any number, say 2, 2.5, 0.9, 0.95 etc.)
Any help is most welcome,
Thanks,
Sriram.
Assuming k is of an integer type, you could use if (k % 2 == 0) ... to check if kis divisible by two:
if (k % 2 == 0)
p[k] = q[k / 2];
else
p[k] = 0;
This can also be expressed using the ternary operator:
p[k] = (k % 2 == 0) ? q[k / 2] : 0;
Presuming that the coef can be anything else,
p[floor(coef*k)] = (fabs(coef*k-floor(coef*k))<1E-6)?q[k]:0;
The short syntax for what you want to do could be this:
p[k] = k % 2 ? 0 : q[k/2];
Is there a way to distinguish between a whole number and an integer in C++?
Define whole number, and define integer in this context. I'm confused!
Are you taking about the difference as explained here?
If you want to detect whether a number is integer or not, then probably this may help:
#include<cmath>
bool IsInteger(double d)
{
double intpart;
return std::modf(double number, &intpart) == 0.0;
}
k % 2 is in a couple of answers in this thread.
However, this is not useful in answering the OP's question. Note the edit:
"Edit: The 0.5 in the above case is only illustrative. It could be any number, say 2, 2.5, 0.9, 0.95 etc.)"
k % 2 only works because the value chosen was 0.5. It won't hold true for any other values.
Therefore, unless I'm missing something entirely, the simplest approach I can think of is the following:
Subtract the floor of the number from the number itself. If the result is > 0, it is not an integer.
Unless you have expressions that result in irrational numbers, you could use Boost.Rational to represent your indizes.
#Aix's suggestion of k%2 looks like it'd combine nicely with the ?: operator:
p[k] = (k%2) ? 0 : q[k/2];