Rounding value to nearest power of two - c#

I am looking for the fastest way in C# to round a value to the nearest power of two.
I've discovered that the fastest way to round a value to the next power of two if to use bitwise operators like this.
int ToNextNearest(int x)
{
if (x < 0) { return 0; }
--x;
x |= x >> 1;
x |= x >> 2;
x |= x >> 4;
x |= x >> 8;
x |= x >> 16;
return x + 1;
}
But this gives the next nearest and not the nearest and I would like to only have the nearest power of two.
Here is a simple way to do that.
int ToNearest(int x)
{
Math.Pow(2, Math.Round(Math.Log(x) / Math.Log(2)));
}
But is there a better optimized version of finding the nearest power of two value ?
Thanks a lot.

Surely the best way is to use your bitwise routine to find the next power of two, then divide that result by two. This gives you the previous power of two. Then a simple comparison will tell you which of the two is closer.
int ToNearest(int x)
{
int next = ToNextNearest(x);
int prev = next >> 1;
return next - x < x - prev ? next : prev;
}
Untested code but you get the idea.

I'm using this:
public static int CeilPower2(int x)
{
if (x < 2) {
return 1;
}
return (int) Math.Pow(2, (int) Math.Log(x-1, 2) + 1);
}
public static int FloorPower2(int x)
{
if (x < 1) {
return 1;
}
return (int) Math.Pow(2, (int) Math.Log(x, 2));
}

On .Net Core, the fastest way to do this would probably to use the intrinsics operations:
private static int NearestPowerOf2(uint x)
{
return 1 << (sizeof(uint) * 8 - BitOperations.LeadingZeroCount(x - 1));
}
On CPU supporting the LZCNT instructions, it is just 6 CPU instructions, without branching.

.Net6 has introduced a method for this
using System.Numerics;
var nearestPowOf2 = BitOperations.RoundUpToPowerOf2(100); //returns 128

How about this:
int ToNearest(int val, int pow)
{
if (pow < 0) return 0;
if (pow == 0) return val;
if (val & (1 << (pow - 1))) {
return ((val >> pow) + 1) << pow;
} else {
return (val >> pow) << pow;
}
}

Haven't tested but i think this could work
int ToNearest(value x)
{
int num = 0;
for(int i=1; i < 65; i++)
{
int cur = Math.Abs(value - 0<<i);
if(Math.Abs(value - 0<<i) < Math.Abs(value - num))
num = cur;
else if(num != 0) break;
}
return num;
}

This is the full implementation of the suggested solution of #john, with the change that it will round up if the value is exactly in between the next and previous power of two.
public static int RoundToNextPowerOfTwo(int a)
{
int next = CeilToNextPowerOfTwo(a);
int prev = next >> 1;
return next - a <= a - prev ? next : prev;
}
public static int CeilToNextPowerOfTwo(int number)
{
int a = number;
int powOfTwo = 1;
while (a > 1)
{
a = a >> 1;
powOfTwo = powOfTwo << 1;
}
if (powOfTwo != number)
{
powOfTwo = powOfTwo << 1;
}
return powOfTwo;
}

Since C# requires IEEE754 floats there is probably a faster way on any platform that does not emulate the floating point functions:
int ToNearestPowerOf2(int x) =>
1 << (int)(BitConverter.DoubleToInt64Bits(x + x/3) >> 52) - 1023;
Rationale:
x + x/3
nearest power of 2, basically *4/3
(BitConverter.DoubleToInt64Bits(x) >> 52) - 1023
take floating point exponent for floor(ln2(x))
1 << x
exponential function with base 2
The function obviously requires a positive value for x.
0 won't work because the closest power of 2 is -∞,
and negative values have a complex logarithms.
Whether this is the fastest way will probably highly depend on what the JIT optimizer squeezes out of the code, more specifically how it handles the hard pointer cast in DoubleToInt64Bits. This may prevent other optimizations.
You do not have to use any comparison to get the nearest power of 2. Since all powers of two are separated by the same factor the rounding point is always at 3/4 of the next power of 2 (i.e. exactly the topmost 2 bits are set). So multiplication by the reciprocal followed by truncation will do the job.

Related

Function to convert bit position to int

I have two functions to convert Bit Position to Integer and back to Bit Position. The senior developer doesn't like that I use a loop for the IntegerToBitPosition function. Is there any way to make it better? I think it's okay, but he said "Just somebody like you could use a loop to calculate something." Only one bit can be set and if there's more than one bit set, it's okay to return the first one.
private int IntToBitPosition(int intValue)
{
int bitValue = 1;
if (intValue == bitValue)
{
return 0;
}
for (var bitPosition = 1; bitPosition < 32; i++)
{
bitValue *= 2;
if (bitValue == intValue)
{
return bitPosition;
}
}
return 0;
}
private int BitPositionToInt(int bitPosition)
{
int intValue = 0;
intValue |= 1 << bitPosition;
return intValue;
}
Remember what binary is, the power of twos. To convert a bit to an int, it's simply 2 to the power of the bit position.
So BitPositionToInt is 2^bitPosition
So 2^4 = 16
The opposite of that is to take the log of a value with base 2. In c#, you can use the Math.Log function
e.g. if the value is 16
Math.Log(16, 2)
Which returns 4.
Note that this won't return the "first" bit position if the int isn't a value to the power of 2. If you want to do that, you still need a loop, but you can certainly simplify it.
private int IntToBitPosition(int value){
int position=0;
while((value & 1)==0 && value>0){
position++;
value= value >> 1;
}
return position;
}
So what we are doing here is ANDing the value with 1 to see if the 0 bit is set. If it's not, right shift the value (which divides it by 2), and check again until the bit is set, or the value is 0.
(note, I didn't typecheck the above routine, but you should get the point).
You can use a switch statement for instant (as in O(1) time complexity) lookups of any predefined integer value - given your range is 1-32 that's straightforward:
private static int IntToBitPosition( int value )
{
switch( value )
{
case 1 << 0: return 1; // The compiler will change `1 << 0` to a constant value allowing its use in a O(1) switch.
case 1 << 1: return 2;
case 1 << 2: return 3;
case 1 << 3: return 4;
case 1 << 4: return 5;
case 1 << 5: return 6;
// etc
case 1 << 28: return 29;
case 1 << 29: return 30;
case 1 << 30: return 31;
case 1 << 31: return 32;
default : return 0;
}
}
If you're using Visual Studio and/or MSBuild (I assume you are) then you can save yourself the trouble of writing the switch cases by hand by using T4:
private static int IntToBitPosition( int value )
{
switch( value )
{
<# for( Int32 i = 0; i <= 31; i++ ) { #>
case << <#= ( 1 << i ) #>: return <#= i + 1 #>
<# } #>
default: return 0;
}
}
Of course, more astute readers will be aware that your IntToBitPosition function is really just doing Log2(n) + 1, which can be computed instantly for any integer using this approach:
public static int Log2(int v)
{
int r = 0xFFFF - v >> 31 & 0x10;
v >>= r;
int shift = 0xFF - v >> 31 & 0x8;
v >>= shift;
r |= shift;
shift = 0xF - v >> 31 & 0x4;
v >>= shift;
r |= shift;
shift = 0x3 - v >> 31 & 0x2;
v >>= shift;
r |= shift;
r |= (v >> 1);
return r;
}
If you are targeting .NET Core 3.0 or .NET 5, you could use BitOperations.Log2(int).
private int IntToBitPosition(int intValue)
{
return System.Numerics.BitOperations.Log2(intValue);
}

Average of 3 long integers

I have 3 very large signed integers.
long x = long.MaxValue;
long y = long.MaxValue - 1;
long z = long.MaxValue - 2;
I want to calculate their truncated average. Expected average value is long.MaxValue - 1, which is 9223372036854775806.
It is impossible to calculate it as:
long avg = (x + y + z) / 3; // 3074457345618258600
Note: I read all those questions about average of 2 numbers, but I don't see how that technique can be applied to average of 3 numbers.
It would be very easy with the usage of BigInteger, but let's assume I cannot use it.
BigInteger bx = new BigInteger(x);
BigInteger by = new BigInteger(y);
BigInteger bz = new BigInteger(z);
BigInteger bavg = (bx + by + bz) / 3; // 9223372036854775806
If I convert to double, then, of course, I lose precision:
double dx = x;
double dy = y;
double dz = z;
double davg = (dx + dy + dz) / 3; // 9223372036854780000
If I convert to decimal, it works, but also let's assume that I cannot use it.
decimal mx = x;
decimal my = y;
decimal mz = z;
decimal mavg = (mx + my + mz) / 3; // 9223372036854775806
Question: Is there a way to calculate the truncated average of 3 very large integers only with the usage of long type? Don't consider that question as C#-specific, just it is easier for me to provide samples in C#.
This code will work, but isn't that pretty.
It first divides all three values (it floors the values, so you 'lose' the remainder), and then divides the remainder:
long n = x / 3
+ y / 3
+ z / 3
+ ( x % 3
+ y % 3
+ z % 3
) / 3
Note that the above sample does not always work properly when having one or more negative values.
As discussed with Ulugbek, since the number of comments are exploding below, here is the current BEST solution for both positive and negative values.
Thanks to answers and comments of Ulugbek Umirov, James S, KevinZ, Marc van Leeuwen, gnasher729 this is the current solution:
static long CalculateAverage(long x, long y, long z)
{
return (x % 3 + y % 3 + z % 3 + 6) / 3 - 2
+ x / 3 + y / 3 + z / 3;
}
static long CalculateAverage(params long[] arr)
{
int count = arr.Length;
return (arr.Sum(n => n % count) + count * (count - 1)) / count - (count - 1)
+ arr.Sum(n => n / count);
}
NB - Patrick has already given a great answer. Expanding on this you could do a generic version for any number of integers like so:
long x = long.MaxValue;
long y = long.MaxValue - 1;
long z = long.MaxValue - 2;
long[] arr = { x, y, z };
var avg = arr.Select(i => i / arr.Length).Sum()
+ arr.Select(i => i % arr.Length).Sum() / arr.Length;
Patrick Hofman has posted a great solution. But if needed it can still be implemented in several other ways. Using the algorithm here I have another solution. If implemented carefully it may be faster than the multiple divisions in systems with slow hardware divisors. It can be further optimized by using divide by constants technique from hacker's delight
public class int128_t {
private int H;
private long L;
public int128_t(int h, long l)
{
H = h;
L = l;
}
public int128_t add(int128_t a)
{
int128_t s;
s.L = L + a.L;
s.H = H + a.H + (s.L < a.L);
return b;
}
private int128_t rshift2() // right shift 2
{
int128_t r;
r.H = H >> 2;
r.L = (L >> 2) | ((H & 0x03) << 62);
return r;
}
public int128_t divideby3()
{
int128_t sum = {0, 0}, num = new int128_t(H, L);
while (num.H || num.L > 3)
{
int128_t n_sar2 = num.rshift2();
sum = add(n_sar2, sum);
num = add(n_sar2, new int128_t(0, num.L & 3));
}
if (num.H == 0 && num.L == 3)
{
// sum = add(sum, 1);
sum.L++;
if (sum.L == 0) sum.H++;
}
return sum;
}
};
int128_t t = new int128_t(0, x);
t = t.add(new int128_t(0, y));
t = t.add(new int128_t(0, z));
t = t.divideby3();
long average = t.L;
In C/C++ on 64-bit platforms it's much easier with __int128
int64_t average = ((__int128)x + y + z)/3;
You can calculate the mean of numbers based on the differences between the numbers rather than using the sum.
Let's say x is the max, y is the median, z is the min (as you have). We will call them max, median and min.
Conditional checker added as per #UlugbekUmirov's comment:
long tmp = median + ((min - median) / 2); //Average of min 2 values
if (median > 0) tmp = median + ((max - median) / 2); //Average of max 2 values
long mean;
if (min > 0) {
mean = min + ((tmp - min) * (2.0 / 3)); //Average of all 3 values
} else if (median > 0) {
mean = min;
while (mean != tmp) {
mean += 2;
tmp--;
}
} else if (max > 0) {
mean = max;
while (mean != tmp) {
mean--;
tmp += 2;
}
} else {
mean = max + ((tmp - max) * (2.0 / 3));
}
Patching Patrick Hofman's solution with supercat's correction, I give you the following:
static Int64 Avg3 ( Int64 x, Int64 y, Int64 z )
{
UInt64 flag = 1ul << 63;
UInt64 x_ = flag ^ (UInt64) x;
UInt64 y_ = flag ^ (UInt64) y;
UInt64 z_ = flag ^ (UInt64) z;
UInt64 quotient = x_ / 3ul + y_ / 3ul + z_ / 3ul
+ ( x_ % 3ul + y_ % 3ul + z_ % 3ul ) / 3ul;
return (Int64) (quotient ^ flag);
}
And the N element case:
static Int64 AvgN ( params Int64 [ ] args )
{
UInt64 length = (UInt64) args.Length;
UInt64 flag = 1ul << 63;
UInt64 quotient_sum = 0;
UInt64 remainder_sum = 0;
foreach ( Int64 item in args )
{
UInt64 uitem = flag ^ (UInt64) item;
quotient_sum += uitem / length;
remainder_sum += uitem % length;
}
return (Int64) ( flag ^ ( quotient_sum + remainder_sum / length ) );
}
This always gives the floor() of the mean, and eliminates every possible edge case.
Because C uses floored division rather than Euclidian division, it may easier to compute a properly-rounded average of three unsigned values than three signed ones. Simply add 0x8000000000000000UL to each number before taking the unsigned average, subtract it after taking the result, and use an unchecked cast back to Int64 to get a signed average.
To compute the unsigned average, compute the sum of the top 32 bits of the three values. Then compute the sum of the bottom 32 bits of the three values, plus the sum from above, plus one [the plus one is to yield a rounded result]. The average will be 0x55555555 times the first sum, plus one third of the second.
Performance on 32-bit processors might be enhanced by producing three "sum" values each of which is 32 bits long, so that the final result is ((0x55555555UL * sumX)<<32) + 0x55555555UL * sumH + sumL/3; it might possibly be further enhanced by replacing sumL/3 with ((sumL * 0x55555556UL) >> 32), though the latter would depend upon the JIT optimizer [it might know how to replace a division by 3 with a multiply, and its code might actually be more efficient than an explicit multiply operation].
If you know you have N values, can you just divide each value by N and sum them together?
long GetAverage(long* arrayVals, int n)
{
long avg = 0;
long rem = 0;
for(int i=0; i<n; ++i)
{
avg += arrayVals[i] / n;
rem += arrayVals[i] % n;
}
return avg + (rem / n);
}
You could use the fact that you can write each of the numbers as y = ax + b, where x is a constant. Each a would be y / x (the integer part of that division). Each b would be y % x (the rest/modulo of that division). If you choose this constant in an intelligent way, for example by choosing the square root of the maximum number as a constant, you can get the average of x numbers without having problems with overflow.
The average of an arbitrary list of numbers can be found by finding:
( ( sum( all A's ) / length ) * constant ) +
( ( sum( all A's ) % length ) * constant / length) +
( ( sum( all B's ) / length )
where % denotes modulo and / denotes the 'whole' part of division.
The program would look something like:
class Program
{
static void Main()
{
List<long> list = new List<long>();
list.Add( long.MaxValue );
list.Add( long.MaxValue - 1 );
list.Add( long.MaxValue - 2 );
long sumA = 0, sumB = 0;
long res1, res2, res3;
//You should calculate the following dynamically
long constant = 1753413056;
foreach (long num in list)
{
sumA += num / constant;
sumB += num % constant;
}
res1 = (sumA / list.Count) * constant;
res2 = ((sumA % list.Count) * constant) / list.Count;
res3 = sumB / list.Count;
Console.WriteLine( res1 + res2 + res3 );
}
}
I also tried it and come up with a faster solution (although only by a factor about 3/4). It uses a single division
public static long avg(long a, long b, long c) {
final long quarterSum = (a>>2) + (b>>2) + (c>>2);
final long lowSum = (a&3) + (b&3) + (c&3);
final long twelfth = quarterSum / 3;
final long quarterRemainder = quarterSum - 3*twelfth;
final long adjustment = smallDiv3(lowSum + 4*quarterRemainder);
return 4*twelfth + adjustment;
}
where smallDiv3 is division by 3 using multipliation and working only for small arguments
private static long smallDiv3(long n) {
assert -30 <= n && n <= 30;
// Constants found rather experimentally.
return (64/3*n + 10) >> 6;
}
Here is the whole code including a test and a benchmark, the results are not that impressive.
This function computes the result in two divisions. It should generalize nicely to other divisors and word sizes.
It works by computing the double-word addition result, then working out the division.
Int64 average(Int64 a, Int64 b, Int64 c) {
// constants: 0x10000000000000000 div/mod 3
const Int64 hdiv3 = UInt64(-3) / 3 + 1;
const Int64 hmod3 = UInt64(-3) % 3;
// compute the signed double-word addition result in hi:lo
UInt64 lo = a; Int64 hi = a>=0 ? 0 : -1;
lo += b; hi += b>=0 ? lo<b : -(lo>=UInt64(b));
lo += c; hi += c>=0 ? lo<c : -(lo>=UInt64(c));
// divide, do a correction when high/low modulos add up
return hi>=0 ? lo/3 + hi*hdiv3 + (lo%3 + hi*hmod3)/3
: lo/3+1 + hi*hdiv3 + Int64(lo%3-3 + hi*hmod3)/3;
}
Math
(x + y + z) / 3 = x/3 + y/3 + z/3
(a[1] + a[2] + .. + a[k]) / k = a[1]/k + a[2]/k + .. + a[k]/k
Code
long calculateAverage (long a [])
{
double average = 0;
foreach (long x in a)
average += (Convert.ToDouble(x)/Convert.ToDouble(a.Length));
return Convert.ToInt64(Math.Round(average));
}
long calculateAverage_Safe (long a [])
{
double average = 0;
double b = 0;
foreach (long x in a)
{
b = (Convert.ToDouble(x)/Convert.ToDouble(a.Length));
if (b >= (Convert.ToDouble(long.MaxValue)-average))
throw new OverflowException ();
average += b;
}
return Convert.ToInt64(Math.Round(average));
}
Try this:
long n = Array.ConvertAll(new[]{x,y,z},v=>v/3).Sum()
+ (Array.ConvertAll(new[]{x,y,z},v=>v%3).Sum() / 3);

Can Math.Round in C# be used for whole integer values?

I have integer 363 for example.
Any method to make it 360 or 365?
This is a hack, but it works:
var rounded = Math.Round(363 / 5f) * 5;
There's nothing built-in, you're just going to have to code the logic yourself. Here's one such method. (Going down is clearer, but going up is manageable.)
int number = 363;
int roundedDown = number - number % 5;
int roundedUp = number + (number % 5 > 0 ? (5 - number % 5) : 0);
Edit for negative numbers, the logic almost gets reversed.
static int RoundUpToFive(int number)
{
if (number >= 0)
return number + (number % 5 > 0 ? (5 - number % 5) : 0);
else
return number - (number % 5);
}
static int RoundDownToFive(int number)
{
if (number >= 0)
return number - number % 5;
else
return number + (number % 5 < 0 ? (-5 - number % 5) : 0);
}
Here's what I usually do, which is a combination of the two ideas:
static int RoundDown(int x, int n) {
return x / n * n;
}
static int Round(int x, int n) {
return (x + n / 2) / n * n;
}
static int RoundUp(int x, int n) {
return (x + n - 1) / n * n;
}
(That assumes positive numbers; Extending it to negatives is straight-forward.)
[edit]
According to LLVM, the Round function can also be written like this:
int Round(int x, int n) {
int z = (x + n / 2);
return z - (z % n);
}
Which you may find more elegant.

Counting common bits in a sequence of unsigned longs

I am looking for a faster algorithm than the below for the following. Given a sequence of 64-bit unsigned integers, return a count of the number of times each of the sixty-four bits is set in the sequence.
Example:
4608 = 0000000000000000000000000000000000000000000000000001001000000000
4097 = 0000000000000000000000000000000000000000000000000001000000000001
2048 = 0000000000000000000000000000000000000000000000000000100000000000
counts 0000000000000000000000000000000000000000000000000002101000000001
Example:
2560 = 0000000000000000000000000000000000000000000000000000101000000000
530 = 0000000000000000000000000000000000000000000000000000001000010010
512 = 0000000000000000000000000000000000000000000000000000001000000000
counts 0000000000000000000000000000000000000000000000000000103000010010
Currently I am using a rather obvious and naive approach:
static int bits = sizeof(ulong) * 8;
public static int[] CommonBits(params ulong[] values) {
int[] counts = new int[bits];
int length = values.Length;
for (int i = 0; i < length; i++) {
ulong value = values[i];
for (int j = 0; j < bits && value != 0; j++, value = value >> 1) {
counts[j] += (int)(value & 1UL);
}
}
return counts;
}
A small speed improvement might be achieved by first OR'ing the integers together, then using the result to determine which bits you need to check. You would still have to iterate over each bit, but only once over bits where there are no 1s, rather than values.Length times.
I'll direct you to the classical: Bit Twiddling Hacks, but your goal seems slightly different than just typical counting (i.e. your 'counts' variable is in a really weird format), but maybe it'll be useful.
The best I can do here is just get silly with it and unroll the inner-loop... seems to have cut the performance in half (roughly 4 seconds as opposed to the 8 in yours to process 100 ulongs 100,000 times)... I used a qick command-line app to generate the following code:
for (int i = 0; i < length; i++)
{
ulong value = values[i];
if (0ul != (value & 1ul)) counts[0]++;
if (0ul != (value & 2ul)) counts[1]++;
if (0ul != (value & 4ul)) counts[2]++;
//etc...
if (0ul != (value & 4611686018427387904ul)) counts[62]++;
if (0ul != (value & 9223372036854775808ul)) counts[63]++;
}
that was the best I can do... As per my comment, you'll waste some amount (I know not how much) running this in a 32-bit environment. If your that concerned over performance it may benefit you to first convert the data to uint.
Tough problem... may even benefit you to marshal it into C++ but that entirely depends on your application. Sorry I couldn't be more help, maybe someone else will see something I missed.
Update, a few more profiler sessions showing a steady 36% improvement. shrug I tried.
Ok let me try again :D
change each byte in 64 bit integer into 64 bit integer by shifting each bit by n*8 in lef
for instance
10110101 -> 0000000100000000000000010000000100000000000000010000000000000001
(use the lookup table for that translation)
Then just sum everything togeter in right way and you got array of unsigned chars whit integers.
You have to make 8*(number of 64bit integers) sumations
Code in c
//LOOKTABLE IS EXTERNAL and has is int64[256] ;
unsigned char* bitcounts(int64* int64array,int len)
{
int64* array64;
int64 tmp;
unsigned char* inputchararray;
array64=(int64*)malloc(64);
inputchararray=(unsigned char*)input64array;
for(int i=0;i<8;i++) array64[i]=0; //set to 0
for(int j=0;j<len;j++)
{
tmp=int64array[j];
for(int i=7;tmp;i--)
{
array64[i]+=LOOKUPTABLE[tmp&0xFF];
tmp=tmp>>8;
}
}
return (unsigned char*)array64;
}
This redcuce speed compared to naive implemetaton by factor 8, becuase it couts 8 bit at each time.
EDIT:
I fixed code to do faster break on smaller integers, but I am still unsure about endianess
And this works only on up to 256 inputs, becuase it uses unsigned char to store data in. If you have longer input string, you can change this code to hold up to 2^16 bitcounts and decrease spped by 2
const unsigned int BYTESPERVALUE = 64 / 8;
unsigned int bcount[BYTESPERVALUE][256];
memset(bcount, 0, sizeof bcount);
for (int i = values.length; --i >= 0; )
for (int j = BYTESPERVALUE ; --j >= 0; ) {
const unsigned int jth_byte = (values[i] >> (j * 8)) & 0xff;
bcount[j][jth_byte]++; // count byte value (0..255) instances
}
unsigned int count[64];
memset(count, 0, sizeof count);
for (int i = BYTESPERVALUE; --i >= 0; )
for (int j = 256; --j >= 0; ) // check each byte value instance
for (int k = 8; --k >= 0; ) // for each bit in a given byte
if (j & (1 << k)) // if bit was set, then add its count
count[i * 8 + k] += bcount[i][j];
Another approach that might be profitable, would be to build an array of 256 elements,
which encodes the actions that you need to take in incrementing the count array.
Here is a sample for a 4 element table, which does 2 bits instead of 8 bits.
int bitToSubscript[4][3] =
{
{0}, // No Bits set
{1,0}, // Bit 0 set
{1,1}, // Bit 1 set
{2,0,1} // Bit 0 and bit 1 set.
}
The algorithm then degenerates to:
pick the 2 right hand bits off of the number.
Use that as a small integer to index into the bitToSubscriptArray.
In that array, pull off the first integer. That is the number of elements in the count array, that you need to increment.
Based on that count, Iterate through the remainder of the row, incrementing count, based on the subscript you pull out of the bitToSubscript array.
Once that loop is done, shift your original number two bits to the right.... Rinse Repeat as needed.
Now there is one issue I ignored, in that description. The actual subscripts are relative. You need to keep track of where you are in the count array. Every time you loop, you add two to an offset. To That offset, you add the relative subscript from the bitToSubscript array.
It should be possible to scale up to the size you want, based on this small example. I would think that another program could be used, to generate the source code for the bitToSubscript array, so that it can be simply hard coded in your program.
There are other variation on this scheme, but I would expect it to run faster on average than anything that does it one bit at a time.
Good Hunting.
Evil.
I believe this should give a nice speed improvement:
const ulong mask = 0x1111111111111111;
public static int[] CommonBits(params ulong[] values)
{
int[] counts = new int[64];
ulong accum0 = 0, accum1 = 0, accum2 = 0, accum3 = 0;
int i = 0;
foreach( ulong v in values ) {
if (i == 15) {
for( int j = 0; j < 64; j += 4 ) {
counts[j] += ((int)accum0) & 15;
counts[j+1] += ((int)accum1) & 15;
counts[j+2] += ((int)accum2) & 15;
counts[j+3] += ((int)accum3) & 15;
accum0 >>= 4;
accum1 >>= 4;
accum2 >>= 4;
accum3 >>= 4;
}
i = 0;
}
accum0 += (v) & mask;
accum1 += (v >> 1) & mask;
accum2 += (v >> 2) & mask;
accum3 += (v >> 3) & mask;
i++;
}
for( int j = 0; j < 64; j += 4 ) {
counts[j] += ((int)accum0) & 15;
counts[j+1] += ((int)accum1) & 15;
counts[j+2] += ((int)accum2) & 15;
counts[j+3] += ((int)accum3) & 15;
accum0 >>= 4;
accum1 >>= 4;
accum2 >>= 4;
accum3 >>= 4;
}
return counts;
}
Demo: http://ideone.com/eNn4O (needs more test cases)
http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetNaive
One of them
unsigned int v; // count the number of bits set in v
unsigned int c; // c accumulates the total bits set in v
for (c = 0; v; c++)
{
v &= v - 1; // clear the least significant bit set
}
Keep in mind, that complexity of this method is aprox O(log2(n)) where n is the number to count bits in, so for 10 binary it need only 2 loops
You should probably take the metod for counting 32 bits whit 64 bit arithmetics and applying it on each half of word, what would take by 2*15 + 4 instructions
// option 3, for at most 32-bit values in v:
c = ((v & 0xfff) * 0x1001001001001ULL & 0x84210842108421ULL) % 0x1f;
c += (((v & 0xfff000) >> 12) * 0x1001001001001ULL & 0x84210842108421ULL) %
0x1f;
c += ((v >> 24) * 0x1001001001001ULL & 0x84210842108421ULL) % 0x1f;
If you have sse4,3 capable processor you can use POPCNT instruction.
http://en.wikipedia.org/wiki/SSE4

Using recursion to add odd numbers

I am trying to write a method to calculate the sum of the odd numbers in all the numbers less than the given number. so eg. CalcOdd(7) would return 5 + 3 + 1 = 9. CalcOdd (10) would return 9 + 7 + 5 + 3 + 1 = 25 etc
The method needs to take in a number, subtract 1, then recursively work backwards adding all odd numbers until it reaches 0. This is what I have so far.
private static int CalcOdd(int n)
{
if (n <= 1)
return 1;
else
if (n % 2 == 0)
n--;
return n + CalcOdd(n - 2);
}
It doesn't work so well, it includes the number passed in in the addition which is not what I want. Can anyone suggest a better way of doing this ? I would also loke to be able to port the answer to work for even numbers and add the option to include the original passed in number in the answer.
Many thanks
Why would you use recursion here? Just loop; or better, figure out the math to do it in a simple equation...
The fact is that C# doesn't make for excellent deep recursion for things like maths; the tail-call isn't really there at the moment.
Loop approach:
private static int CalcOdd(int n)
{
int sum = 0, i = 1;
while (i < n)
{
sum += i;
i += 2;
}
return sum;
}
You could do this with recursion as you say, but if you wish to do it quicker, then I can tell you that the sum of the n first odd numbers is equal to n*n.
private static int CalcOdd(int n) {
if (n<=1)
return 0;
if (n%2 == 1)
n--;
int k = n/2;
return k*k;
}
The reason this works is:
Every even number is of the form 2k, and the odd number before it is 2k-1.
Because 2*1-1 = 1, there are k odd numbers below 2k.
If n is odd, we don't want to include it, so we simply go down to the even number below it and we automatically have what we want.
Edited to fix broken code.
the sum of odd numbers less than a given number is a perfect square.
get the whole part of (n/2) to get the number of odd number less than itself.
square that and voila!
private static int CalcSumOdd(int n)
{
int i;
int.tryParse(n / 2, out i);
return i*i;
}
for even numbers its:
int i = n/2;
return i*(i+1);
correction. The above "even number sum" includes the original number "n". ie fn(12) = 42 = 2 + 4 + 6 + 8 + 10 + 12
if you want to exclude it, you should either unilaterally exclude it, or remove it with logic based on a passed in parameter.
Here is a correction,
int CalcOdd(int n)
{
n--; // <----
if (n <= 1)
return 0; // <----
else
if (n % 2 == 0)
n--;
return n + CalcOdd(n); // <----
}
i'm new here but this seems like a silly recursion exercise, given it can be done with a simple equation:
int sum(n,isEven,notFirst) {
int c=1; //skip the else
if (isEven) c=2;
if (notFirst) n-=2;
return ((n+c)*((n+c)/2))/2; }
classic discrete math sum series..
sum from 1 to 100 (odds and evens) is ((100+1)*(100/2))=5050
edit: in my code here, if you're calculating the sum of odds with n being even, or vice versa, it doesn't work, but i'm not going to put the work into that (and slop the code) right now. i'll assume your code will take care of that by the time it hits the function.. for example 7/2 isn't an int (obviously)
Why use recursion?
private Int32 CalcOdd(Int32 value)
{
Int32 r = 0;
{
while (value >= 1)
{
value--;
if (value % 2 != 0)
{
r += value;
}
}
}
return r;
}
Use a helper function. CalcOdd consists of testing n to see if it is even or odd; if it is even, return helper(n); if it is odd, return helper(n-2).
The helper function must handle three cases:
1) n is less than 1; in this case return 0.
2) n is even, in this case return helper(n-1).
3) n is odd, in this case return n+helper(n-1).
public static int CalcOdd(int n) {
// Find the highest even number. (Either n, or n-1.)
// Divide that by 2, and the answer should be the square of that number.
n = (n & 0x3FFFFFFE) >> 1;
return (int)Math.Pow(n, 2);
}
private static int CalcOdd(int n) {
n -= 1;
if ((n & 1) == 0) n--;
if (n <= 1) return 1;
return n + CalcOdd(n - 1);
}
But I would say doing loops is better and cleaner.
private static int CalcOdd(int n) {
int i, r = 1;
for (i = 3; i < n; i+=2)
r += i;
return r;
}
Since you want the option of including or excluding the first answer (and, keeping your "recursion" constraint in mind):
int calcOdd(int n, bool includeN)
{
if( !includeN )
return calcOdd(n-1, true);
if(n<=1)
return 1;
else
if(n%2 == 0)
n--;
return n+calcOdd(n-1, true);
}
The includeFirst, if passed as true, will include n in the calculations. Otherwise, the next layer down will start "including N".
Granted, as others have said, this is a horribly inefficient use of recursion, but... If you like recursion, try Haskell. It's a language built almost entirely on the concept.
int CalcOdd(int n)
{
n -= 1;
if (n <= 0)
return 0;
if (n % 2 == 0)
n--;
return n + CalcOdd(n);
}
This function is also recursive, and it has parameters which makes you able to decide wether to do even or odd number and wether you want to include the first number or not. If you are confused as to how it works, remember that bools also can be seen as 1 (true) and 0 (false)
int Calc(int n, bool even = false, bool includeFirst = false)
{
n -= !includeFirst;
if (n <= 0)
return 0;
if (n % 2 == even)
n--;
return n + Calc(n - includeFirst, even);
}
Håkon, I have ported your code to c# in VS 2008 as follows
static int Calc(int n, bool bEven, bool bIncludeFirst)
{
int iEven = Bool2Int(bEven);
int iIncludeFirst = Bool2Int(bIncludeFirst);
n -= 1 - iIncludeFirst;
if (n <= 0)
return 0;
if (n % 2 == iEven)
n--;
return n + Calc(n - iIncludeFirst, bEven, bIncludeFirst);
}
private static int Bool2Int(bool b)
{
return b ? 1 : 0;
}
It seems to be working. Now is there anything I can do to optomise ? i.e. I dont want to have to parse those bools to ints every time etc ?
I'd isolate the 'make it odd' part from the 'sum every other descending number' part: (forgive the Python)
def sumEveryTwoRecursive(n):
if n <= 0:
return 0
return n + sumEveryTwoRecursive(n - 2)
def calcOdd(n):
return sumEveryTwoRecursive(n - (2 if n % 2 else 1))
Just because there isn't one here yet, I've decided to use the LINQ hammer on this nail...
(borrowed from Nick D and Jason's pair programmed answer here)
void Main()
{
GetIterator(7, true, false).Sum().Dump();
// Returns 9
GetIterator(10, true, false).Sum().Dump();
// Returns 25
}
public IEnumerable<int> GetIterator(int n, bool isOdd, bool includeOriginal)
{
if (includeOriginal)
n++;
if (isOdd)
return GetIterator(n, 1);
else
return GetIterator(n, 0);
}
public IEnumerable<int> GetIterator(int n, int odd)
{
n--;
if (n < 0)
yield break;
if (n % 2 == odd)
yield return n;
foreach (int i in GetIterator(n, odd))
yield return i;
}
#include <iostream>
using namespace std;
int sumofodd(int num);
int main()
{
int number,res;
cin>>number;
res=sumofodd(number);
cout<<res;
return 0;
}
int sumofodd(int num)
{ if(num<1) return 0;
if (num%2==0) num--;
return num+sumofodd(num-1);
}

Categories

Resources