What does this recursive function do - c

i am doing some exam prep and one of the question is to describe what the following piece of C code does.
int g(int *a, int b ,int c){
if(b==c) return a[b];
return g(a,b,(b+c)/2) + g(a,(b+c)/2+1 ,c);}
Cant seem to figure out the recursion, from my understanding the sum of the left hand
is sum of the series b+2^n/2*c and sum of the series of right to be (2^n/2)*(b+c) where n starts at 0. But there is no value for n that will make the series to be equal b or c respectively. Does that mean if the first if condition isn't meet it will continue on for infinity?

Assuming b < c, g() returns the sum of the elements of the array a[] from index b to index c (both inclusive)
In other words,
g( a, b, c ) :=
int sum = 0;
for( int i = b; i <= c; ++i )
sum += a[ i ];
return sum;
EDIT Proof Sketch
Assume c - b = n
(b + c)/2
= (c - b + 2b)/2
= (c - b)/2 + b
= b + n/2
Thus, g( a, b, (b + c)/2 ) + g( a, (b + c)/2 + 1, c )
= g( a, b, b + n/2 ) + g( a, b + n/2 + 1, c )

Related

How can I compute a * b / c when both a and b are smaller than c, but a * b overflows?

Assuming that uint is the largest integral type on my fixed-point platform, I have:
uint func(uint a, uint b, uint c);
Which needs to return a good approximation of a * b / c.
The value of c is greater than both the value of a and the value of b.
So we know for sure that the value of a * b / c would fit in a uint.
However, the value of a * b itself overflows the size of a uint.
So one way to compute the value of a * b / c would be:
return a / c * b;
Or even:
if (a > b)
return a / c * b;
return b / c * a;
However, the value of c is greater than both the value of a and the value of b.
So the suggestion above would simply return zero.
I need to reduce a * b and c proportionally, but again - the problem is that a * b overflows.
Ideally, I would be able to:
Replace a * b with uint(-1)
Replace c with uint(-1) / a / b * c.
But no matter how I order the expression uint(-1) / a / b * c, I encounter a problem:
uint(-1) / a / b * c is truncated to zero because of uint(-1) / a / b
uint(-1) / a * c / b overflows because of uint(-1) / a * c
uint(-1) * c / a / b overflows because of uint(-1) * c
How can I tackle this scenario in order to find a good approximation of a * b / c?
Edit 1
I do not have things such as _umul128 on my platform, when the largest integral type is uint64. My largest type is uint, and I have no support for anything larger than that (neither on the HW level, nor in some pre-existing standard library).
My largest type is uint.
Edit 2
In response to numerous duplicate suggestions and comments:
I do not have some "larger type" at hand, which I can use for solving this problem. That is why the opening statement of the question is:
Assuming that uint is the largest integral type on my fixed-point platform
I am assuming that no other type exists, neither on the SW layer (via some built-in standard library) nor on the HW layer.
needs to return a good approximation of a * b / c
My largest type is uint
both a and b are smaller than c
Variation on this 32-bit problem:
Algorithm: Scale a, b to not overflow
SQRT_MAX_P1 as a compile time constant of sqrt(uint_MAX + 1)
sh = 0;
if (c >= SQRT_MAX_P1) {
while (|a| >= SQRT_MAX_P1) a/=2, sh++
while (|b| >= SQRT_MAX_P1) b/=2, sh++
while (|c| >= SQRT_MAX_P1) c/=2, sh--
}
result = a*b/c
shift result by sh.
With an n-bit uint, I expect the result to be correct to at least about n/2 significant digits.
Could improve things by taking advantage of the smaller of a,b being less than SQRT_MAX_P1. More on that later if interested.
Example
#include <inttypes.h>
#define IMAX_BITS(m) ((m)/((m)%255+1) / 255%255*8 + 7-86/((m)%255+12))
// https://stackoverflow.com/a/4589384/2410359
#define UINTMAX_WIDTH (IMAX_BITS(UINTMAX_MAX))
#define SQRT_UINTMAX_P1 (((uintmax_t)1ull) << (UINTMAX_WIDTH/2))
uintmax_t muldiv_about(uintmax_t a, uintmax_t b, uintmax_t c) {
int shift = 0;
if (c > SQRT_UINTMAX_P1) {
while (a >= SQRT_UINTMAX_P1) {
a /= 2; shift++;
}
while (b >= SQRT_UINTMAX_P1) {
b /= 2; shift++;
}
while (c >= SQRT_UINTMAX_P1) {
c /= 2; shift--;
}
}
uintmax_t r = a * b / c;
if (shift > 0) r <<= shift;
if (shift < 0) r >>= shift;
return r;
}
#include <stdio.h>
int main() {
uintmax_t a = 12345678;
uintmax_t b = 4235266395;
uintmax_t c = 4235266396;
uintmax_t r = muldiv_about(a,b,c);
printf("%ju\n", r);
}
Output with 32-bit math (Precise answer is 12345677)
12345600
Output with 64-bit math
12345677
Here is another approach that uses recursion and minimal approximation to achieve high precision.
First the code and below an explanation.
Code:
uint32_t bp(uint32_t a) {
uint32_t b = 0;
while (a!=0)
{
++b;
a >>= 1;
};
return b;
}
int mul_no_ovf(uint32_t a, uint32_t b)
{
return ((bp(a) + bp(b)) <= 32);
}
uint32_t f(uint32_t a, uint32_t b, uint32_t c)
{
if (mul_no_ovf(a, b))
{
return (a*b) / c;
}
uint32_t m = c / b;
++m;
uint32_t x = m*b - c;
// So m * b == c + x where x < b and m >= 2
uint32_t n = a/m;
uint32_t r = a % m;
// So a*b == n * (c + x) + r*b == n*c + n*x + r*b where r*b < c
// Approximation: get rid of the r*b part
uint32_t res = n;
if (r*b > c/2) ++res;
return res + f(n, x, c);
}
Explanation:
The multiplication a * b can be written as a sum of b
a * b = b + b + .... + b
Since b < c we can take a number m of these b so that (m-1)*b < c <= m*b, like
(b + b + ... + b) + (b + b + ... + b) + .... + b + b + b
\---------------/ \---------------/ + \-------/
m*b + m*b + .... + r*b
\-------------------------------------/
n times m*b
so we have
a*b = n*m*b + r*b
where r*b < c and m*b > c. Consequently, m*b is equal to c + x, so we have
a*b = n*(c + x) + r*b = n*c + n*x + r*b
Divide by c :
a*b/c = (n*c + n*x + r*b)/c = n + n*x/c + r*b/c
The values m, n, x, r can all be calculated from a, b and c without any loss of
precision using integer division (/) and remainder (%).
The approximation is to look at r*b (which is less than c) and "add zero" when r*b<=c/2
and "add one" when r*b>c/2.
So now there are two possibilities:
1) a*b = n + n*x/c
2) a*b = (n + 1) + n*x/c
So the problem (i.e. calculating a*b/c) has been changed to the form
MULDIV(a1,b1,c) = NUMBER + MULDIV(a2,b2,c)
where a2,b2 is less than a1,b2. Consequently, recursion can be used until
a2*b2 no longer overflows (and the calculation can be done directly).
I've established a solution which work in O(1) complexity (no loops):
typedef unsigned long long uint;
typedef struct
{
uint n;
uint d;
}
fraction;
uint func(uint a, uint b, uint c);
fraction reducedRatio(uint n, uint d, uint max);
fraction normalizedRatio(uint a, uint b, uint scale);
fraction accurateRatio(uint a, uint b, uint scale);
fraction toFraction(uint n, uint d);
uint roundDiv(uint n, uint d);
uint func(uint a, uint b, uint c)
{
uint hi = a > b ? a : b;
uint lo = a < b ? a : b;
fraction f = reducedRatio(hi, c, (uint)(-1) / lo);
return f.n * lo / f.d;
}
fraction reducedRatio(uint n, uint d, uint max)
{
fraction f = toFraction(n, d);
if (n > max || d > max)
f = normalizedRatio(n, d, max);
if (f.n != f.d)
return f;
return toFraction(1, 1);
}
fraction normalizedRatio(uint a, uint b, uint scale)
{
if (a <= b)
return accurateRatio(a, b, scale);
fraction f = accurateRatio(b, a, scale);
return toFraction(f.d, f.n);
}
fraction accurateRatio(uint a, uint b, uint scale)
{
uint maxVal = (uint)(-1) / scale;
if (a > maxVal)
{
uint c = a / (maxVal + 1) + 1;
a /= c; // we can now safely compute `a * scale`
b /= c;
}
if (a != b)
{
uint n = a * scale;
uint d = a + b; // can overflow
if (d >= a) // no overflow in `a + b`
{
uint x = roundDiv(n, d); // we can now safely compute `scale - x`
uint y = scale - x;
return toFraction(x, y);
}
if (n < b - (b - a) / 2)
{
return toFraction(0, scale); // `a * scale < (a + b) / 2 < MAXUINT256 < a + b`
}
return toFraction(1, scale - 1); // `(a + b) / 2 < a * scale < MAXUINT256 < a + b`
}
return toFraction(scale / 2, scale / 2); // allow reduction to `(1, 1)` in the calling function
}
fraction toFraction(uint n, uint d)
{
fraction f = {n, d};
return f;
}
uint roundDiv(uint n, uint d)
{
return n / d + n % d / (d - d / 2);
}
Here is my test:
#include <stdio.h>
int main()
{
uint a = (uint)(-1) / 3; // 0x5555555555555555
uint b = (uint)(-1) / 2; // 0x7fffffffffffffff
uint c = (uint)(-1) / 1; // 0xffffffffffffffff
printf("0x%llx", func(a, b, c)); // 0x2aaaaaaaaaaaaaaa
return 0;
}
You can cancel prime factors as follows:
uint gcd(uint a, uint b)
{
uint c;
while (b)
{
a %= b;
c = a;
a = b;
b = c;
}
return a;
}
uint func(uint a, uint b, uint c)
{
uint temp = gcd(a, c);
a = a/temp;
c = c/temp;
temp = gcd(b, c);
b = b/temp;
c = c/temp;
// Since you are sure the result will fit in the variable, you can simply
// return the expression you wanted after having those terms canceled.
return a * b / c;
}

Optimizing a nested loop in C

I have a nested loop to find all possible combinations of numbers between 1 and x in groups of 4, where a < b < c < d.
A method is called as each group is discovered to do a simple equivalency test on the sum of those numbers.
The loop does work and produces expected output (1 set of numbers for this particular x), however it takes 12+ seconds to find this answer and another ~5 to test the remaining possibilities, which is definitely bad, considering the x values are < 1000.
I tried having the outer loop iterate a < x - 3 times, the b loop b < x - 2 times, down to d < x times which didn't make a noticeable difference.
What would be a better approach in changing this loop?
for (a = 1; a < x; a++) {
for (b = a + 1; b < x; b++) {
for (c = b + 1; c < x; c++) {
for (d = c + 1; d < x; d++) {
check(a, b, c, d);
}
}
}
}
With such a deep level of nesting, any early exit you can introduce - particularly at the outer loops - could net big gains.
For example, you write that check is testing a + b + c + d == x && a * b * c * d == x - so you can compute the intermediate sum and product, and break when you encounter numbers that would make any selection of later numbers impossible.
An example:
for (a = 1; a < x; a++) {
for (b = a + 1; b < x; b++) {
int sumAB = a + b;
if (sumAB + sumAB > x) break;
int prodAB = a * b;
if (prodAB * prodAB > x) break;
for (c = b + 1; c < x; c++) {
int sumABC = sumAB + c;
if (sumABC + c > x) break;
int prodABC = prodAB * c;
if (prodABC * c > x) break;
for (d = c + 1; d < x; d++) {
int sumABCD = sumABC + d;
if (sumABCD > x) break;
if (sumABCD != x) continue;
int prodABCD = prodABC * d;
if (prodABCD > x) break;
if (prodABCD != x) continue;
printf("%d, %d, %d, %d\n", a, b, c, d);
}
}
}
}
This is just an example - you can constrain all the checks here further (e.g. make the first check be sumAB + sumAB + 3 > x). The point is to focus on early exits.
I added a counter for each loop, counting how many times it was entered, and tried your version and my version, with x = 100. My version has orders of magnitude less loop entries:
No early exits: 99, 4851, 156849, 3764376
With early exits: 99, 4851, 1122, 848

Converting for() loop to do{}while in C with nested loops

I am trying to write a program that will find all acute triangle solutions after the user enters a min and max value (dmin and dmax). Right now I think I have the program working using only for() loops, but I need to change the first for() loop to a do{}while loop, which is confusing me. I'm not able to figure out how to write the do{}while loop so that is also includes these nested for() loops and the if statements. Everything I've tried either tells me b and c aren't being used or it just runs and provides no output. Here is my code with the for() loops.
double a = 0, b = 0, c = 0;
printf("Here are the acute triangle solutions the program found:\n");
for (c = dmin; c <= dmax, c++)
{
for (b = dmin; b <= dmax; b++)
{
for (a = dmin; a <= dmax; a++)
{
if (a * a + b * b - c == c * c ){ //
if (((a + b) > c) && ((b + c) > a) && ((b + a) > b))
{printf("(%lf %lf %lf)\n", a, b, c);}
//sum of two sides must be greater than the third
//and angle across from c must be <90 degrees
}
}
}
}
a for (e1;e2;e3) something loop can be transformed in:
e1;
while (e2) {
something;
e3;
}
or:
e1;
if (e2) {
do {
something;
e3;
} while (e2);
}
In a do while, you simply do an initialization before and the check after. It is really somewhat similar to what the system does for a for loop.
The following code:
for (c = dmin; c <= dmax, c++)
{
for (b = dmin; b <= dmax; b++)
{
for (a = dmin; a <= dmax; a++)
{
if (a * a + b * b - c == c * c ){ //
if (((a + b) > c) && ((b + c) > a) && ((c + a) > c))
{printf("(%lf %lf %lf)\n", a, b, c);}
//sum of two sides must be greater than the third
//and angle across from c must be <90 degrees
}
}
}
}
Becomes:
c = dmin;
if(c < dmax) { //Make sure not to run once if c is greater
do
{
for (b = dmin; b <= dmax; b++)
{
for (a = dmin; a <= dmax; a++)
{
if (a * a + b * b - c == c * c ){ //
if (((a + b) > c) && ((b + c) > a) && ((c + a) > b))
{printf("(%lf %lf %lf)\n", a, b, c);}
//sum of two sides must be greater than the third
//and angle across from c must be <90 degrees
}
}
}
} while( ++c <= dmax );
}

Sum in C, from two numbers

Im creating a simple program in C that user insert a number, for example 5 and the program sums until 5, 0+1+2+3+4. Im using this formula
int sum_naturals(int n){
return (n-1)*n/2;
}
But now i want a formula that can sum from 2 different numbers, like user inserts number 5 and 9 and the program will do 5+6+7+8+9.
Can someone have ideia how can resolve this? Thanks
You can reuse your function
int sum(int a, int b) {
return sum_naturals(b) - sum_naturals(a-1)
}
Of course you have to add some validation.
Why not this?
int sum_2_naturals(int n, int m){
return (sum_naturals(m) - sum_naturals(n))
}
But now i want a formula that can sum from 2 different numbers,
To find the sum of a certain number of terms of an arithmetic sequence:
#include <stdio.h>
static int sum_naturals(int a, int b)
{
return ((b - a + 1) * (a + b)) / 2;
}
int main(void)
{
printf("%d\n", sum_naturals(5, 9));
return 0;
}
Output:
35
More info
Looks like a simple task, but since you still have problems understanding it, why don't you 'define' your functions first - before 'coding' them.
S(n) = 0 + 1 + 2 + ... + n-1 = n(n-1)/2
F(k,n) = k + k+1 + ... + n-1 + n = -(0 + 1 + ... + k-1) + (0 + 1 + ... + k-1) + k + k+1 + ... + n-1 + n = -S(k) + S(n) + n = S(n+1) - S(k)
Of course, need to assume that k <= n etc.
I guess the reason of all confusion is that you defined your basic function to sum from 0 to n-1, instead of 1 to n.

the Floating-point error

#include <stdio.h>
int main()
{
int n;
while ( scanf( "%d", &n ) != EOF ) {
double sum = 0,k;
if( n > 5000000 || n<=0 ) //the judgment of the arrange
break;
for ( int i = 1; i <= n; i++ ) {
k = (double) 1 / i;
sum += k;
}
/*
for ( int i = n; i > 0; i-- ) {
k = 1 / (double)i;
sum += k;
}
*/
printf("%.12lf\n", sum);
}
return 0;
}
Why in the different loop I get the different answer. Is there a float-error? When I input 5000000 the sum is 16.002164235299 but as I use the other loop of for (notation part) I get the sum 16.002164235300.
Because floating point math is not associative:
i.e. (a + b) + c is not necessarily equal to a + (b + c)
I also bumped into a + b + c issue. Totally agreed with ArjunShankar.
// Here A != B in general case
float A = ( (a + b) + c) );
float B = ( (a + c) + b) );
Most of floating point operations are performed with data loss in mantis, even when components are fit well in it (numbers like 0.5 or 0.25).
In fact I was quite happy to find out the cause of bug in my application. I have written short reminder article with detailed explanation:
http://stepan.dyatkovskiy.com/2018/04/machine-fp-partial-invariance-issue.html
Below is the C example. Good luck!
example.c
#include <stdio.h>
// Helpers declaration, for implementation scroll down
float getAllOnes(unsigned bits);
unsigned getMantissaBits();
int main() {
// Determine mantissa size in bits
unsigned mantissaBits = getMantissaBits();
// Considering mantissa has only 3 bits, we would then get:
// a = 0b10 m=1, e=1
// b = 0b110 m=11, e=1
// c = 0b1000 m=1, e=3
// a + b = 0b1000, m=100, e=1
// a + c = 0b1010, truncated to 0b1000, m=100, e=1
// a + b + c result: 0b1000 + 0b1000 = 0b10000, m=100, e=2
// a + c + b result: 0b1000 + 0b110 = 0b1110, m=111, e=1
float a = 2,
b = getAllOnes(mantissaBits) - 1,
c = b + 1;
float ab = a + b;
float ac = a + c;
float abc = a + b + c;
float acb = a + c + b;
printf("\n"
"FP partial invariance issue demo:\n"
"\n"
"Mantissa size = %i bits\n"
"\n"
"a = %.1f\n"
"b = %.1f\n"
"c = %.1f\n"
"(a+b) result: %.1f\n"
"(a+c) result: %.1f\n"
"(a + b + c) result: %.1f\n"
"(a + c + b) result: %.1f\n"
"---------------------------------\n"
"diff(a + b + c, a + c + b) = %.1f\n\n",
mantissaBits,
a, b, c,
ab, ac,
abc, acb,
abc - acb);
return 1;
}
// Helpers
float getAllOnes(unsigned bits) {
return (unsigned)((1 << bits) - 1);
}
unsigned getMantissaBits() {
unsigned sz = 1;
unsigned unbeleivableHugeSize = 1024;
float allOnes = 1;
for (;sz != unbeleivableHugeSize &&
allOnes + 1 != allOnes;
allOnes = getAllOnes(++sz)
) {}
return sz-1;
}

Resources