C bit operation puzzle - c

/*
* ezThreeFourths - multiplies by 3/4 rounding toward 0,
* Should exactly duplicate effect of C expression (x*3/4),
* including overflow behavior.
* Examples: ezThreeFourths(11) = 8
* ezThreeFourths(-9) = -6
* ezThreeFourths(1073741824) = -268435456 (overflow)
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 12
* Rating: 3
*/
int ezThreeFourths(int x) {
int z = x+x+x;
int sign_z = z>>31;
return ((z>>2)&(~sign_z)) + (((z>>2)+1)&sign_z);
}
I tried to solve this puzzle but
ERROR: Test ezThreeFourths(-2147483648[0x80000000]) failed...
...Gives -536870911[0xe0000001]. Should be -536870912[0xe0000000]
compiled with gcc (GCC) 4.1.2 20080704 (Red Hat 4.1.2-51)
What's wrong with this solution?

Here's what I did:
#include <stdio.h>
#include <limits.h>
int ThreeFourths(int x)
{
int x3 = x + x + x;
return (x3 >= 0) ? (x3 >> 2) : -(int)((UINT_MAX - x3 + 1) >> 2);
}
int testData[] =
{
0,
1,
-1,
2,
-2,
3,
-3,
4,
-4,
5,
-5,
-9,
11,
INT_MAX / 2 + 1,
INT_MIN
};
int main(void)
{
int i;
for (i = 0; i < sizeof(testData)/sizeof(testData[0]); i++)
{
printf(" %d * 3 / 4 = %d\n",
testData[i], testData[i] * 3 / 4);
printf("ThreeFourths(%d) = %d\n",
testData[i], ThreeFourths(testData[i]));
}
return 0;
}
Output:
0 * 3 / 4 = 0
ThreeFourths(0) = 0
1 * 3 / 4 = 0
ThreeFourths(1) = 0
-1 * 3 / 4 = 0
ThreeFourths(-1) = 0
2 * 3 / 4 = 1
ThreeFourths(2) = 1
-2 * 3 / 4 = -1
ThreeFourths(-2) = -1
3 * 3 / 4 = 2
ThreeFourths(3) = 2
-3 * 3 / 4 = -2
ThreeFourths(-3) = -2
4 * 3 / 4 = 3
ThreeFourths(4) = 3
-4 * 3 / 4 = -3
ThreeFourths(-4) = -3
5 * 3 / 4 = 3
ThreeFourths(5) = 3
-5 * 3 / 4 = -3
ThreeFourths(-5) = -3
-9 * 3 / 4 = -6
ThreeFourths(-9) = -6
11 * 3 / 4 = 8
ThreeFourths(11) = 8
1073741824 * 3 / 4 = -268435456
ThreeFourths(1073741824) = -268435456
-2147483648 * 3 / 4 = -536870912
ThreeFourths(-2147483648) = -536870912
The reason why I didn't use right shifts on negative integers is simple. The result of these shifts is implementation-defined (per the C standard) and is not guaranteed to be the same as from a right shift with sign extension that we might be expecting because of it being the most common implementation.
I wrote (UINT_MAX - x3 + 1) instead of simply -x3 because it can result a signed overflow (when x3 = INT_MIN that is a minus power of 2), which has undefined behavior (per the C standard, again). And even if this undefined behavior is known to be harmless, simple negation could still fail to produce a positive number (because of the asymmetry in the 2's complement representation of signed integers).
x + x + x can still produce signed overflow just as x * 3 can. So, this is the same undefined behavior.
Btw, since signed overflows result in UB, it should not even be legally asked from you to achieve them, let alone have specific expectations about the results when UB occurs.

int ezThreeFourths(int x) {
int z = x+x+x;
int sign_z = z>>31;
return ((z>>2)&(~sign_z)) + (((z>>2)+1)&sign_z);
}
Works with non-negative numbers. Also you shouldn't lie about code "you" wrote. Considering the exact code was written in "2008-01-26"

Works fine for me using Embarcadero C++ 6.43:
// x = 2147483647
int ezThreeFourths(int x)
{
int z = x+x+x;
// z = 2147483645 (6442450941[0x17FFFFFFD] truncated to 32-bits!)
int sign_z = z>>31;
// sign_z = (2147483645 >> 31) = 0
return ((z>>2)&(~sign_z)) + (((z>>2)+1)&sign_z);
// = ((2147483645 >> 2) & (~0)) + (((2147483645 >> 2) + 1) & 0)
// = (536870911 & 0xFFFFFFFF) + ((536870911+1) & 0)
// = (536870911 & 0xFFFFFFFF) + (536870912 & 0)
// = (536870911 & 0xFFFFFFFF) + 0
// = (536870911 & 0xFFFFFFFF)
// = 536870911
}

Your approach for making negative numbers round towards zero is not working correctly in the case of input values that divide evenly by 4. 0x80000000 is one such example, but it's perhaps easier to see the problem if you try with a small value.
For example: ezThreeFourths(-8) = -5 [ should be -6 ]

Related

Fibonacci sequence with 32 bit overflow algorithm

I am currently implementing a code that runs Fibonacci sequence (up to the 60th number) in riscv32I, which means that the memory address that I can use only has 32bits.
I have first implemented the code in C, and then in Assembly, but I am curious if the algorithm I used has a name so I can do more research. The code is as such,
#include <stdint.h>
#include <stdio.h>
#include <inttypes.h>
int main() {
uint32_t n1 = 0; // first pre number (n - 2)
uint32_t n2 = 1; // second pre number (n - 1)
uint32_t add = 0; // current number
uint32_t store_hi = 0;
uint32_t store_lo = 0;
uint32_t result; // result
uint32_t carry; // carry bit
for (int i = 2; i < 61; i++) {
carry = 0; // reset carry bit
add = (uint32_t)(n2 + n1); // calculate current fib number
if (add < n1) { // if overflow
carry = 1; // set carry bit
}
result = store_hi + store_lo; // keeping track of higher bits
result = result + carry; // add carry bit
store_lo = store_hi; //
n1 = n2; // update first pre number
store_hi = result; //
n2 = add; // update second pre number
}
printf("Result32: 0x%08" PRIx32 " 0x%08" PRIx32 "\n", result, add);
uint64_t result64 = ((uint64_t)result << 32) | add;
printf("Result64: 0x%016" PRIx64 " -> %" PRId64 "\n", result64, result64);
}
Running the code gives
Result32: 0x00000168 0x6c8312d0
Result64: 0x000001686c8312d0 -> 1548008755920
The basic concept is that because the Fibonacci number gets too big to fit within a single 32bit memory address, we have to split it into 32bit memory address, one holding the upper bit, and one holding the lower bit.
Let's generalize the above algorithm to a 4 bit memory space, to make it easier to follow the algorithm. This means that the maximum int can be 16. Let ss set n1 = 10, n2 = 10.
Loop 1:
add = 4 # (10 + 10 = 20, but overflow, so 20 % 16 = 4)
carry = 1
result = 1
store_lo = 0
store_hi = 1
n1 = 10
n2 = 4
# output: 0x14, 0x1 hi bit, 0x4 lo bit, which is 10 + 10 = 20
Loop 2:
add = 14
carry = 0
result = 1
store_lo = 1
store_hi = 1
n1 = 4
n2 = 14
# output: 0x1e, 0x1 hi bit, 0xe or 14, lo bit, which is 10 + 20 = 30
loop 3:
add = 2 (14 + 4 = 18, but overflow, so 18 % 16, 2)
carry = 1
result = 3
store_lo = 1
store_hi = 2
n1 = 14
n2 = 2
#output: 0x32, 0x3 hi bit, 0x2 low bit, which is 20 + 30 = 50
.... and so on.
This should work for any base, but I am curious what this algorithm is denoted as, or if it is simply related to modules and powers?
Thanks!
It's called Arbitrary-precision arithmetic, you can read more about it here.
Arbitrary-precision arithmetic, also called bignum arithmetic, multiple-precision arithmetic, or sometimes infinite-precision arithmetic, indicates that calculations are performed on numbers whose digits of precision are limited only by the available memory of the host system.
One of the troubles of venturing from 32-bit to 64-bit is that the now distant horizon rapidly becomes as constraining as the former, "closer" horizon was.
Below is a sketch of an "ASCII digit" Fibonacci calculator. Its two seeds are "0" and "1" at the right end of two 20 character buffers. (20 is arbitrary, but takes one beyond the 60th value in the Fibonacci sequence.) This could be optimised and improved in a hundred different ways. It is a "powers of ten" version that uses two ASCII strings for its storage. One could, if one was patient, use 1000 character buffer, or 10,000 to go deep into the Fibonacci realm...
I hope you find this interesting.
EDIT: #Chux has pointed out that the sequence generated below indexes from 1, whereas indexing from 0 is correct. The simple fix (not shown here) would be to change three instances of ++fn to fn++ (an exercise left to the reader.) Thank you again, #Chux!
#include <stdio.h>
int main() {
char f[2][20 + 1], *fmt = "%s %-3d";
int fn = 0;
sprintf( f[0], "%20s", "0" );
sprintf( f[1], "%20s", "1" );
printf( fmt, f[ 0 ], ++fn );
putchar( '\n' );
printf( fmt, f[ 1 ], ++fn );
for( bool evod = false; getchar() != EOF; evod = !evod ) {
for( int carry = 0, i = 20; --i >= 0; ) {
if( f[ evod][i] == ' ' && f[!evod][i] == ' ' && carry == 0 ) break;
int f1 = f[ evod][i] == ' ' ? 0 : f[ evod][i] - '0';
int f2 = f[!evod][i] == ' ' ? 0 : f[!evod][i] - '0';
f1 += f2 + carry; carry = f1 / 10; f[ evod][i] = f1%10 + '0';
}
printf( fmt, f[ evod], ++fn );
}
return 0;
}
Output
0 1
1 2
1 3
2 4
3 5
5 6
8 7
13 8
21 9
/* omitted */
591286729879 59
956722026041 60
1548008755920 61
2504730781961 62
4052739537881 63

Optimize the Sum of Digits of N

Codewars Question: (Sum of Digits / Digital Root)
Given n, take the sum of the digits of n. If that value has more than one digit, continue reducing in this way until a single-digit number is produced. The input will be a non-negative integer.
Test Cases:
16 --> 1 + 6 = 7
942 --> 9 + 4 + 2 = 15 --> 1 + 5 = 6
132189 --> 1 + 3 + 2 + 1 + 8 + 9 = 24 --> 2 + 4 = 6
493193 --> 4 + 9 + 3 + 1 + 9 + 3 = 29 --> 2 + 9 = 11 --> 1 + 1 = 2
My code:
#include <bits/stdc++.h>
using namespace std;
int singleDigit(int n)
{
int ans;
while (n > 0)
{
int lastDigit = n % 10;
n /= 10;
ans += lastDigit;
}
while (ans > 9)
{
int n1 = ans;
ans = 0;
while (n1 > 0)
{
int lastDigit = n1 % 10;
n1 /= 10;
ans += lastDigit;
}
}
return ans;
}
int main()
{
cout << singleDigit(49319366) << endl;
return 0;
}
Is there a better or optimized way to solve this problem or to reduce time complexity?
This function works for non-negative integers, adapting for negative numbers is straightforward.
int singleDigit(int n)
{
return (n-1) % 9 + 1;
}
It has the following advantages:
no variables to forget to initialise
no loops to commit an off-by-one error
fast
The disadvantages are:
it is not immediately clear how or why it works
For more information on the last bullet point, see:
Direct formulas for the digital root
Modulo operation with negative numbers

logical AND operation for two binary number in C

I should find result of "1001011 AND 1001010=1001010"...How can I find the result of this process in C programmin without using & symbol? Thanks for your help...
You can perform this operation one bit at a time and get the result using the multiplication operator:
unsigned and(unsigned a, unsigned b) {
unsigned mul = 1, res = 0;
while ((a != 0) * (b != 0)) {
res += mul * (a % 2) * (b % 2);
a /= 2;
b /= 2;
mul *= 2;
}
return res;
}
For a more efficient approach, use the Boolean algebraic equivalence:
unsigned and(unsigned a, unsigned b) { return ~(~a | ~b); }
This sounds a bit like homework, so...
The truth table for AND is:
0 AND 0 = 0
0 AND 1 = 0
1 AND 0 = 0
1 AND 1 = 1
The truth table for OR is:
0 OR 0 = 0
0 OR 1 = 1
1 OR 0 = 1
1 OR 1 = 1
What happens if you swap all the 0's and 1's in the bottom table?
NOT 0 OR NOT 0 = ?
NOT 0 OR NOT 1 = ?
NOT 1 OR NOT 0 = ?
NOT 1 OR NOT 1 = ?
I hope this helps, without giving the game away completely!

How to find couples of numbers with the same sum from 1 to n and from n+1 to m

So, I have to make a work for college and it consists in creating an algorithm.
The algorithm must find couples of numbers which satisfy a certain condition, which is: the sum from 1 to n (exlusive) results the same as the sum from n+1 to m (inclusive).
At the final, the algorithm must give at least 15 couples.
The first couple is 6 and 8, because from 1 to n (exclusive) (6) is 1+2+3+4+5 = 15 and from n+1 to m is 8+7 = 15.
The algorithm I created is the following one:
int main() {
int count = 0;
unsigned int before = 0;
unsigned int after = 0;
unsigned int n = 1;
unsigned int m = 0;
do {
before += n - 1;
after = n + 1;
for (m = after + 1; after < before; m++) {
after += m;
}
if (before == after) {
printf("%d\t%d\n", n, (m - 1));
count++;
}
n++;
} while (count < 15);
}
This is actually OK, but some of the output are not correct, and its also crap, in terms of complexity, and since I am studying Complexity of Algorithms, it would be good to find some algorithm better than this one.
I also tried doing it in Java, but using int is not good for this problem and using long, it takes hours and hours to compute.
The numbers I have found so far:
6 and 8
35 and 49
204 and 288
1189 and 1681
6930 and 9800
40391 and 57121
The following ones may be incorrect:
100469 and 107694
115619 and 134705
121501 and 144689
740802 and 745928
1250970 and 1251592
2096128 and 2097152
2100223 and 2101246
4196352 and 8388608
18912301 and 18912497
Your results are incorrect beyond the first 6: the range of type unsigned int is insufficient to store the sums. You should use type unsigned long long for before and after.
Furthermore, your algorithm becomes very slow for large values because you recompute after from scratch for each new value of before, with a time complexity of O(N2). You can keep 2 running sums in parallel and reduce the complexity to quasi-linear.
Last but not least, there are only 12 solutions below UINT32_MAX, so type unsigned long long, which is guaranteed to have at least 64 value bits is required for n and m as well. To avoid incorrect results, overflow should be tested when updating after.
Further tests show that the sums after and before exceed 64 bits for values of m around 8589934591. A solution is to subtract 262 from both before and after when they reach 263. With this modification, the program can keep searching for larger values of n and m much beyond 32-bits.
Here is an improved version:
#include <stdio.h>
int main() {
int count = 0;
unsigned long long n = 1;
unsigned long long m = 2;
unsigned long long before = 0;
unsigned long long after = 2;
for (;;) {
if (before < after) {
before += n;
n++;
after -= n;
} else {
m++;
/* reduce values to prevent overflow */
if (after > 0x8000000000000000) {
after -= 0x4000000000000000;
before -= 0x4000000000000000;
}
after += m;
while (before > after) {
after += n;
n--;
before -= n;
}
}
if (before == after) {
printf("%llu\t%llu\n", n, m);
count++;
if (count == 15)
break;
}
}
printf("%d solutions up to %llu\n", count, m);
return 0;
}
Output (running time 30 minutes):
6 8
35 49
204 288
1189 1681
6930 9800
40391 57121
235416 332928
1372105 1940449
7997214 11309768
46611179 65918161
271669860 384199200
1583407981 2239277041
9228778026 13051463048
53789260175 76069501249
313506783024 443365544448
15 solutions up to 443365544448
Your initial brute force program as posted above generates plenty of data for you to analyze. The people in the question's comments recommended the "sum of an arithmetic series" formula instead of your repeated addition, but the fact is that it still would run slow. It's surely an improvement, but it's still not good enough if you want something usable.
Believe it or not, there are some patterns to the values of n and m, which will require some math to explain. I'll be using the functions n(i), m(i), and d(i) = m(i) - n(i) to represent the values of n, m, and the difference between them, respectively, during iteration i.
You found the first six couples:
i n(i) m(i) d(i)
== ====== ====== ======
1 6 8 2
2 35 49 14
3 204 288 84
4 1189 1681 492
5 6930 9800 2870
6 40391 57121 16730
Notice that 6+8 = 14, 35+49 = 84, 204+288 = 492, etc. It so happens that, in the general case, d(i+1) = m(i) + n(i) (e.g. d(2) = m(1) + n(1) = 6 + 8 = 14).
So now we know the following:
d(7)
= n(6) + m(6)
= 40391 + 57121
= 97512
# m(i) = n(i) + d(i)
m(7) = n(7) + 97512
Another way of looking at it since m(i) = n(i) + d(i) is d(i+1) = d(i) + 2n(i):
d(7)
= n(6) + d(6) + n(6)
= d(6) + 2n(6)
= 16730 + 2(40391)
= 97512
d(i) also happens to be useful for computing n(i+1):
n(i+1) = 2d(i+1) + n(i) + 1
n(7) = 2d(7) + n(6) + 1
= 2(97512) + 40391 + 1
= 235416
From there, it's easy to determine things:
i n(i) m(i) d(i)
== ====== ====== ======
1 6 2 8
2 35 14 49
3 204 84 288
4 1189 492 1681
5 6930 2870 9800
6 40391 16370 57121
7 235416 332928 97512
But what about a starting condition? We need a way to find 6 in the first place, and that starting case can be computed by working backward and using substitution:
n(1) = 2d(1) + n(0) + 1
6 = 2(2) + n(0) + 1
5 = 4 + n(0)
1 = n(0)
d(1) = d(0) + 2n(0)
2 = d(0) + 2(1)
2 = d(0) + 2
0 = d(0)
m(0) = n(0) + d(0)
= 1 + 0
= 1
Note that n(0) = m(0) (1 = 1), but it is not a couple. For a pair of numbers to be a couple, the numbers must not be the same.
All that's left is to compute the sum. Since the integers from 1 to n-1 (i.e. 1 to n, excluding n) form an arithmetic series and the series starts at 1, you can use the formula
n(n - 1)
S(n) = --------
2
Below is a program that uses all of this information. You'll notice I'm using a multiplication function mul in place of the multiplication operator. The function's result is used to end the loop prematurely when an unsigned overflow (i.e. wraparound) is encountered. There are probably better ways to detect the wraparound behavior, and the algorithm could be better designed, but it works.
#include <errno.h>
#include <limits.h>
#include <stdio.h>
typedef unsigned long long uval_t;
/*
* Uses a version of the "FOIL method" to multiply two numbers.
* If overflow occurs, 0 is returned, and errno is ERANGE.
* Otherwise, no overflow occurs, and the product m*n is returned.
*/
uval_t mul(uval_t m, uval_t n)
{
/*
* Shift amount is half the number of bits in uval_t.
* This allows us to work with the upper and lower halves.
* If the upper half of F is not zero, overflow occurs and zero is returned.
* If the upper half of (O+I << half_shift) + L is not zero,
* overflow occurs and zero is returned.
* Otherwise, the returned value is the mathematically accurate result of m*n.
*/
#define half_shift ((sizeof (uval_t) * CHAR_BIT) >> 1)
#define rsh(v) ((v) >> half_shift)
#define lsh(v) ((v) << half_shift)
uval_t a[2], b[2];
uval_t f, o, i, l;
a[0] = rsh(m);
a[1] = m & ~lsh(a[0]);
b[0] = rsh(n);
b[1] = n & ~lsh(b[0]);
f = a[0] * b[0];
if (f != 0)
{
errno = ERANGE;
return 0;
}
o = a[0] * b[1];
i = a[1] * b[0];
l = a[1] * b[1];
if (rsh(o+i + rsh(l)) != 0)
{
errno = ERANGE;
return 0;
}
return lsh(o+i) + l;
}
int main(void)
{
int i;
uval_t n = 1, d = 0;
uval_t sum = 0;
#define MAX 15
for (i = 1; i <= MAX; i++)
{
d += n * 2;
n += d * 2 + 1;
sum = mul(n, n - 1) / 2;
if (sum == 0)
break;
printf("%2d\t%20llu\t%20llu\t%20llu\n", i, n, n+d, sum);
}
return 0;
}
This yields 12 lines of output, the last being this one:
12 1583407981 2239277041 1253590416355544190
Of course, if you don't care about the sums, then you can just avoid computing them entirely, and you can find all 15 couples just fine without even needing to check for overflow of a 64-bit type.
To go further with the sums, you have a few options, in order of most to least recommended:
use a "bignum" library such as GNU MP, which is similar to Java's java.math.BigInteger class and which has its own printf-like function for displaying values; if you're on Linux, it may already be available
use your compiler's 128-bit type, assuming it has one available, and create your own printing function for it if necessary
create your own "big integer" type and the associated necessary addition, subtraction, multiplication, division, etc. printing functions for it; a way that allows for easy printing is that it could just be two unsigned long long values glued together with one representing the lower 19 decimal digits (i.e. the max value for it would be 999 9999 9999 9999 9999), and the other representing the upper 19 digits for a total of 38 digits, which is 1038-1 or 127 bits
The fact that the full 15 sums required don't fit in 64 bits, however, makes me concerned that the question was perhaps worded badly and wanted something different from what you wrote.
Edit
To prove this works, we must first establish some rules:
For any values n and m, 0 ≤ n < m must be true, meaning n == m is forbidden (else we don't have a couple, a.k.a. "ordered pair").
n and m must both be integers.
With that out of the way, consider an algorithm for computing the sum of an arithmetic series starting at a and ending at, and including, b with a difference of +1 between each successive term:
(b - a + 1)(b + a)
S(a, b) = ------------------
2
b² - a² + b + a
= ---------------
2
b(1 + b) + a(1 - a)
= -------------------
2
If such a series begins at a=1, you can derive a simpler formula:
b(b + 1)
S(b) = --------
2
Applying this to your problem, you want to know how to find values such that the following is true:
S(n-1) = S(n+1, m)
After applying the arguments, the result looks like this:
(n-1)n m(1 + m) + (n+1)[1 - (n+1)]
------ = ---------------------------
2 2
(n-1)n = m(1 + m) + (n+1)(1 - n - 1)
n² - n = m² + m + (n+1)(-n)
n² - n = m² + m - n² - n
2n² = m² + m
While not important for my purposes, it's perhaps worth noting that m² + m can be rewritten as m(m+1), and the 2n² signifies that one or both of m and m+1 must be divisible by 2. In addition, one must be a perfect square while the other must be twice a perfect square due to the requirement that at least one expression must be divisible by 2. In other words, 2n² = m(m+1) = 2x²y². You can find another equally valid solution using x and y to generate the values of n and m, but I won't demonstrate that here.
Given the equations for n(i+1), m(i+1), and d(i+1):
d(i+1) = d(i) + 2n(i)
= m(i) + n(i)
n(i+1) = 2d(i+1) + n(i) + 1
= 2m(i) + 3n(i) + 1
m(i+1) = d(i+1) + n(i+1)
= 3m(i) + 4n(i) + 1
And the starting conditions:
n(0) = 1
d(0) = 0
m(0) = 1
We can determine whether they actually work by substituting i+2 in place of i in all cases and finding whether we end up with the same equation. Assuming f(n(i)) = 2n²(i) and g(m(i)) = m(i) ⋅ (m(i) + 1), the equation f(n(i+2)) = g(m(i+2)) reduces to f(n(i)) = g(m(i)), proving the equations work for any couple:
f(n(i+2))
= g(m(i+2))
f(2m(i+1) + 3n(i+1) + 1)
= g((3m(i+1) + 4n(i+1) + 1))
2 ⋅ (12m(i) + 17n(i) + 6)²
= (17m(i) + 24n(i) + 8) ⋅ (17m(i) + 24n(i) + 8 + 1)
2 ⋅ (144m²(i) + 408m(i)⋅n(i) + 144m(i) + 289n²(i) + 204n(i) + 36)
= 289m²(i) + 816m(i)⋅n(i) + 289m(i) + 576n²(i) + 408n(i) + 72
288m²(i) + 816m(i)⋅n(i) + 288m(i) + 578n²(i) + 408n(i) + 72
= 289m²(i) + 816m(i)⋅n(i) + 289m(i) + 576n²(i) + 408n(i) + 72
2n²(i)
= m²(i) + m(i)
f(n(i))
= g(m(i))
If you're lost toward the end, I simply subtracted 288m²(i) + 816m(i)⋅n(i) + 288m(i) + 576n²(i) + 408n(i) + 72 from both sides of the equation, yielding 2n²(i) = m²(i) + m(i).

how to get elements of euclidean division in C (no the remainder)

alright. I have the Euclidean division like this : a = b * q + r
I know that to get r, I can do the modulo : a % b
but how do I get q ? // doesn't seem to work.
Using Euclidean division
If a = 7 and b = 3, then q = 2 and r = 1, since 7 = 3 × 2 + 1.
If a = 7 and b = −3, then q = −2 and r = 1, since 7 = −3 × (−2) + 1.
If a = −7 and b = 3, then q = −3 and r = 2, since −7 = 3 × (−3) + 2.
If a = −7 and b = −3, then q = 3 and r = 2, since −7 = −3 × 3 + 2.
Likely a more simple solution is available.
int Ediv(int a, int b) {
printf("a:%2d / b:%2d = ", a,b);
int r = a % b;
if (r < 0) r += abs(b);
printf("r:%2d ", r);
return (a - r) / b;
}
void Etest() {
printf("q:%2d\n", Ediv(7,3));
printf("q:%2d\n", Ediv(7,-3));
printf("q:%2d\n", Ediv(-7,3));
printf("q:%2d\n", Ediv(-7,-3));
}
a: 7 / b: 3 = r: 1 q: 2
a: 7 / b:-3 = r: 1 q:-2
a:-7 / b: 3 = r: 2 q:-3
a:-7 / b:-3 = r: 2 q: 3
OP asserts "I know that to get r, I can do the modulo : a % b". This fails when a is negative.
Further, % is the "remainder operator". In C, the difference between Euclidean remainder and modulo occurs when a is negative. Remainder calculation for the modulo operation
If a and b are integers, just use integer division, /.
chux's answer is a good one, as it's the one that correctly understands the question (unlike the accepted one). Daan Leijen's Division and Modulus for Computer Scientists also provides an algorithm with proof:
/* Euclidean quotient */
long quoE(long numer, long denom) {
/* The C99 and C++11 languages define both of these as truncating. */
long q = numer / denom;
long r = numer % denom;
if (r < 0) {
if (denom > 0)
q = q - 1; // r = r + denom;
else {
q = q + 1; // r = r - denom;
}
return q;
}
This one is trivially equivalent to chux's algorithm. It looks a bit more verbose, but it might take one fewer div instruction on x86, as the instruction performs a "divmod" -- returning q and r at the same time.
Take an example:
7 = 3*2 + 1
2 (q) can be obtained by 7/3, i.e, a/b = q.

Resources