I know in java that you can simply reverse a long (101010100000001) by using long.reverse (100000001010101). However, is there anything like these that exists in c#.
The answer to your question is no. However it is achievable by code.
How about this...
public static long RevLong(long l)
{
long tmp = l;
long r = 0L;
if (tmp < 0)
tmp *= -1;
while (tmp > 0)
{
r = (r * 10) + (tmp - ((tmp / 10)) * 10);
tmp = tmp / 10;
}
return r * (l < 0 ? -1 : 1);
}
How about...
public ulong Bit(ulong x, int n)
{
return (x & (1 << n)) >> n;
}
public ulong ReverseBits(ulong x)
{
ulong result = 0;
for (int i = 0; i < 64; i++)
result = result | (x.Bit(64 - i) << i);
return result;
}
Another aproach for reversing a long is:
long num = 123456789;
long reversed = 0;
while (num > 0)
{
reversed = (reversed * 10) + (num % 10);
num /= 10;
}
or
long num = 123456789;
long reversed = 0;
while (num > 0)
{
reversed = (reversed << 1) + (reversed << 3) + (num & 1);
num >>= 1;
}
There are some interesting examples here. You could adapt one of these into an extension method, like so:
public static class LongExtension
{
public static ulong Reverse(this ulong value)
{
return (value & 0x00000000000000FFUL) << 56 | (value & 0x000000000000FF00UL) << 40 |
(value & 0x0000000000FF0000UL) << 24 | (value & 0x00000000FF000000UL) << 8 |
(value & 0x000000FF00000000UL) >> 8 | (value & 0x0000FF0000000000UL) >> 24 |
(value & 0x00FF000000000000UL) >> 40 | (value & 0xFF00000000000000UL) >> 56;
}
}
Then you can call it like this:
ulong myLong = 3L;
ulong reversed = myLong.Reverse();
Hope this will work
string s = 101010100000001.tostring();
char[] charArray = s.ToCharArray();
Array.Reverse( charArray );
return new string( charArray );
Related
I want to get numerator and denominator from decimal and then simplify both numerator and denominator. For example, if decimal is 0.05, then numerator and denominator should be 1/20. Preferably without loops/iterations or least amount of those and without memory heap.
I'm currently using this code, but it results in 0/1 rather than expected 1/20.
public Fraction(double chance) {
long num = 0;
long den = 1;
unchecked {
ulong bitwiseRepr = BitConverter.DoubleToUInt64Bits(chance);
ulong signBit = bitwiseRepr >> 63;
ulong expBits = bitwiseRepr >> 52;
ulong mntsBits = bitwiseRepr & 0x7FFFFFFFFF;
long signFactor = signBit == 1 ? -1 : 1;
if (expBits == 0x0000 || expBits == 0x0800) { // +0, -0
goto NormalWay;
}
else if (expBits == 0x07FF || expBits == 0x0FFF) { // +Inf, -Inf
num = 0;
den = signFactor;
goto NormalWay;
}
else if (expBits == 0x07FFF) { // NaN
num = long.MaxValue;
den = 0;
goto NormalWay;
}
long significand = (long)((1u << 52) | mntsBits);
int nTrailizingZeros = CountTrailingZeroes(significand);
significand >>= nTrailizingZeros;
int exp = (int)expBits - 127 - 52 + nTrailizingZeros;
if (exp < 0) {
num = significand;
den = 1 << -exp;
}
else {
num = signFactor * significand * (1 << exp);
den = 1;
}
goto NormalWay;
}
NormalWay:
numerator = num;
denominator = den;
Normalize();
}
private static int CountTrailingZeroes(long v) {
int counter = 0;
while (counter < 64 && (v & 1u) == 0) {
v >>= 1;
counter++;
}
return counter;
}
[MethodImpl(MethodImplOptions.AggressiveOptimization | MethodImplOptions.AggressiveInlining)]
public void Normalize() {
bool numeratorIsNegative = numerator < 0;
bool denominatorIsNegative = denominator < 0;
if (numeratorIsNegative) {
numerator *= -1;
}
if (denominatorIsNegative) {
denominator *= -1;
}
if (numerator > long.MaxValue / 2 && denominator > long.MaxValue / 2) {
throw new ArithmeticException($"Numerator or denominator are greater than {long.MaxValue / 2} or lesser than {-long.MaxValue / 2}.");
}
numerator += denominator;
Reduce(GCD(numerator, denominator));
Reduce(Math.Sign(denominator));
numerator %= denominator;
if (numeratorIsNegative) {
numerator *= -1;
}
if (denominatorIsNegative) {
denominator *= -1;
}
}
[MethodImpl(MethodImplOptions.AggressiveOptimization | MethodImplOptions.AggressiveInlining)]
private void Reduce(long x) {
numerator /= x;
denominator /= x;
}
[MethodImpl(MethodImplOptions.AggressiveOptimization | MethodImplOptions.AggressiveInlining)]
private static long GCD(long a, long b) {
while (b != 0) {
long t = b;
b = a % b;
a = t;
}
return a;
}
Current code is also going to be less acurate cause it works just for doubles (yet).
As simple as that:
internal static (BigInteger numerator, BigInteger denominator) Fraction(decimal d)
{
int[] bits = decimal.GetBits(d);
BigInteger numerator = (1 - ((bits[3] >> 30) & 2)) *
unchecked(((BigInteger)(uint)bits[2] << 64) |
((BigInteger)(uint)bits[1] << 32) |
(BigInteger)(uint)bits[0]);
BigInteger denominator = BigInteger.Pow(10, (bits[3] >> 16) & 0xff);
return (numerator, denominator);
}
I have an array of ushorts and want to iterate over the array and check if the first two bits of that ushort are 11 if so I want to clear them. However the bit mask I am using to read the first two bits in my conditional are not working properly and the if statement does not trigger when the first two bits are 11
static public void trimData(ushort[] rawData)
{
for(int i = 0; i < rawData.Length; i++)
{
if (((ushort)(rawData[i] & (1 << 15)) == 1) && ((ushort)(rawData[i] & (1 << 14)) == 1))
{
rawData[i] = (ushort)(rawData[i]&~(1<<15));
rawData[i] = (ushort)(rawData[i]&~(1<<14));
}
}
}
How can I use bitmasks to do this correctly?
You can shift these bits to have them being the rightmost ones and then mask with 0b11:
// drop all bits except topmost ones 16 - 14 == 2 which are now the rightmost
int bits = (rawData[i] >> 14) & 0b11;
if (bits == 0b11) {
// Both bits are set
}
To clear these bits you use XOR ^ (since 1 ^ 1 == 0):
int mask = 0b11 << 14;
// remove 14th and 15th set bits
rawData[i] = (ushort)(rawData[i] ^ mask);
Let's combine these parts:
if (((rawData[i] >> 14) & 0b11) == 0b11)
rawData[i] = (ushort)(rawData[i] ^ (0b11 << 14));
Finally, the method can be
public static void trimData(ushort[] rawData) {
if (rawData is null)
throw new ArgumentNullException(nameof(rawData));
for (int i = 0; i < rawData.Length; i++)
if (((rawData[i] >> 14) & 0b11) == 0b11)
rawData[i] = (ushort)(rawData[i] ^ (0b11 << 14));
}
Can you try this?
static public void trimData(ushort[] rawData)
{
for(int i = 0; i < rawData.Length; i++)
{
if (49152 == (49152 & rawData[i]))
{
rawData = rawData.Where(x=>x != rawData[i]).ToArray();
}
}
}
49152 = (2^14) + (2^15)
I'm trying to extend this topic a bit by expanding it to cover 5-bit values packed into a byte[] data structure.
The specific objective I'm trying to achieve would be to store a total of 128 5-bit (0-31) numeric values in a 80-byte array with a get/set function to access and manipulate the values within the array.
Does anyone have experience with this?
Edit:
Thanks to Guffa in the accepted answer below, here's an inline version of his class for use in static calls:
byte Get_5_In_BA(ref byte[] storage, int index)
{
int bigIndex = (index * 5) / 8;
int smallIndex = (index * 5) % 8;
if (smallIndex > 3)
{
return ((byte) (((storage[bigIndex] + (storage[bigIndex + 1] * 0x0100)) >> smallIndex) & 0x1F));
}
return ((byte) ((storage[bigIndex] >> smallIndex) & 0x1F));
}
void Set_5_In_BA(ref byte[] storage, int index, byte value)
{
if (value > 31) { value = 31; }
int bigIndex = (index * 5) / 8;
int smallIndex = (index * 5) % 8;
int mask = 0x1F << smallIndex;
storage[bigIndex] = (byte) ((storage[bigIndex] & ~mask) | (value << smallIndex));
if (smallIndex > 3)
{
storage[bigIndex + 1] = (byte) ((storage[bigIndex + 1] & ~(mask >> 8)) | (value >> (8 - smallIndex)));
}
}
Something like this should do it:
public class FiveBit {
private byte[] _data;
public FiveBit(int len) {
_data = new byte[(len * 5 + 7) / 8];
}
public int this[int index] {
get {
int i = index * 5 / 8;
int ofs = index * 5 % 8;
if (ofs > 3) {
return ((_data[i] + _data[i + 1] * 256) >> ofs) & 31;
} else {
return (_data[i] >> ofs) & 31;
}
}
set {
int i = index * 5 / 8;
int ofs = index * 5 % 8;
int mask = 31 << ofs;
_data[i] = (byte)((_data[i] & ~mask) | (value << ofs));
if (ofs > 3) {
_data[i + 1] = (byte)((_data[i + 1] & ~(mask >> 8)) | (value >> (8 - ofs)));
}
}
}
}
Note: This is not throroughly tested, but I have tested that I can put 128 random 5-bit values in it, and get the same values out again. You should also add some range checks on the parameters to make the code more robust, and I didn't give much thought to the class name so you can surely make up something that describes it better.
I'm writing a time-critical piece of code in C# that requires me to convert two unsigned integers that define an inclusive range into a bit field. Ex:
uint x1 = 3;
uint x2 = 9;
//defines the range [3-9]
// 98 7654 3
//must be converted to: 0000 0011 1111 1000
It may help to visualize the bits in reverse order
The maximum value for this range is a parameter given at run-time which we'll call max_val. Therefore, the bit field variable ought to be defined as a UInt32 array with size equal to max_val/32:
UInt32 MAX_DIV_32 = max_val / 32;
UInt32[] bitArray = new UInt32[MAX_DIV_32];
Given a range defined by the variables x1 and x2, what is the fastest way to perform this conversion?
Try this. Calculate the range of array items that must be filled with all ones and do this by iterating over this range. Finally set the items at both borders.
Int32 startIndex = x1 >> 5;
Int32 endIndex = x2 >> 5;
bitArray[startIndex] = UInt32.MaxValue << (x1 & 31);
for (Int32 i = startIndex + 1; i <= endIndex; i++)
{
bitArray[i] = UInt32.MaxValue;
}
bitArray[endIndex] &= UInt32.MaxValue >> (31 - (x2 & 31));
May be the code is not 100% correct, but the idea should work.
Just tested it and found three bugs. The calculation at start index required a mod 32 and at end index the 32 must be 31 and a logical and instead of a assignment to handle the case of start and end index being the same. Should be quite fast.
Just benchmarked it with equal distribution of x1 and x2 over the array.
Intel Core 2 Duo E8400 3.0 GHz, MS VirtualPC with Server 2003 R2 on Windows XP host.
Array length [bits] 320 160 64
Performance [executions/s] 33 million 43 million 54 million
One more optimazation x % 32 == x & 31 but I am unable to meassure a performance gain. Because of only 10.000.000 iterations in my test the fluctuations are quite high. And I am running in VirtualPC making the situation even more unpredictable.
My solution for setting a whole range of bits in a BitArray to true or false:
public static BitArray SetRange(BitArray bitArray, Int32 offset, Int32 length, Boolean value)
{
Int32[] ints = new Int32[(bitArray.Count >> 5) + 1];
bitArray.CopyTo(ints, 0);
var firstInt = offset >> 5;
var lastInt = (offset + length) >> 5;
Int32 mask = 0;
if (value)
{
// set first and last int
mask = (-1 << (offset & 31));
if (lastInt != firstInt)
ints[lastInt] |= ~(-1 << ((offset + length) & 31));
else
mask &= ~(-1 << ((offset + length) & 31));
ints[firstInt] |= mask;
// set all ints in between
for (Int32 i = firstInt + 1; i < lastInt; i++)
ints[i] = -1;
}
else
{
// set first and last int
mask = ~(-1 << (offset & 31));
if (lastInt != firstInt)
ints[lastInt] &= -1 << ((offset + length) & 31);
else
mask |= -1 << ((offset + length) & 31);
ints[firstInt] &= mask;
// set all ints in between
for (Int32 i = firstInt + 1; i < lastInt; i++)
ints[i] = 0;
}
return new BitArray(ints) { Length = bitArray.Length };
}
You could try:
UInt32 x1 = 3;
UInt32 x2 = 9;
UInt32 newInteger = (UInt32)(Math.Pow(2, x2 + 1) - 1) &
~(UInt32)(Math.Pow(2, x1)-1);
Is there a reason not to use the System.Collections.BitArray class instead of a UInt32[]? Otherwise, I'd try something like this:
int minIndex = (int)x1/32;
int maxIndex = (int)x2/32;
// first handle the all zero regions and the all one region (if any)
for (int i = 0; i < minIndex; i++) {
bitArray[i] = 0;
}
for (int i = minIndex + 1; i < maxIndex; i++) {
bitArray[i] = UInt32.MaxValue; // set to all 1s
}
for (int i = maxIndex + 1; i < MAX_DIV_32; i++) {
bitArray[i] = 0;
}
// now handle the tricky parts
uint maxBits = (2u << ((int)x2 - 32 * maxIndex)) - 1; // set to 1s up to max
uint minBits = ~((1u << ((int)x1 - 32 * minIndex)) - 1); // set to 1s after min
if (minIndex == maxIndex) {
bitArray[minIndex] = maxBits & minBits;
}
else {
bitArray[minIndex] = minBits;
bitArray[maxIndex] = maxBits;
}
I was bored enough to try doing it with a char array and using Convert.ToUInt32(string, int) to convert to a uint from base 2.
uint Range(int l, int h)
{
char[] buffer = new char[h];
for (int i = 0; i < buffer.Length; i++)
{
buffer[i] = i < h - l ? '1' : '0';
}
return Convert.ToUInt32(new string(buffer), 2);
}
A simple benchmark shows that my method is about 5% faster than Angrey Jim's (even if you replace second Pow with a bit shift.)
It is probably the easiest to convert to producing a uint array if the upper bound is too big to fit into a single int. It's a little cryptic but I believe it works.
uint[] Range(int l, int h)
{
char[] buffer = new char[h];
for (int i = 0; i < buffer.Length; i++)
{
buffer[i] = i < h - l ? '1' : '0';
}
int bitsInUInt = sizeof(uint) * 8;
int numNeededUInts = (int)Math.Ceiling((decimal)buffer.Length /
(decimal)bitsInUInt);
uint[] uints = new uint[numNeededUInts];
for (int j = uints.Length - 1, s = buffer.Length - bitsInUInt;
j >= 0 && s >= 0;
j--, s -= bitsInUInt)
{
uints[j] = Convert.ToUInt32(new string(buffer, s, bitsInUInt), 2);
}
int remainder = buffer.Length % bitsInUInt;
if (remainder > 0)
{
uints[0] = Convert.ToUInt32(new string(buffer, 0, remainder), 2);
}
return uints;
}
Try this:
uint x1 = 3;
uint x2 = 9;
int cbToShift = x2 - x1; // 6
int nResult = ((1 << cbToShift) - 1) << x1;
/*
(1<<6)-1 gives you 63 = 111111, then you shift it on 3 bits left
*/
I'm currently writing a quick solution for Euler Problem #4 where one must find the largest palindromic number from the product of two 3-digit numbers.
To identify if a number is palindromic, you would obviously compare a reverse of the number with the original.
Since C# doesn't have a built in String.Reverse() method, what is the quickest way to reverse a string?
I will be testing all the suggested solution in a loop with 100,000,000 iterations. The correct answer will be given to the person who submitted the fastest solution.
I will be testing the solution in a C#.Net 3.5 console application
Wouldn't reversing the number be faster?
// unchecked code, don't kill me if it doesn't even compile.
ulong Reverse(ulong number) {
ulong result = 0;
while (number > 0) {
ulong digit = number % 10;
result = result * 10 + digit;
number /= 10;
}
return result;
}
A you want to compare a number with its reverse it may be faster to reverse the number using division rather than converting it to a string. I still need to test the speed of it.
private static int Reverse(int num) {
int res = 0;
while (num > 0) {
int rm ;
num = Math.DivRem(num, 10, out rm);
res = res * 10 + rm;
}
return res;
}
EDIT:
DivRem was about 1% faster than division and module in my computer.
A speed optimization is exit if the last digit is 0:
private static int Reverse(int num) {
int res = 0;
int rm;
num = Math.DivRem(num, 10, out rm);
//Some magic value or return false, see below.
if (rm == 0) return -1 ;
res = res * 10 + rm;
while (num > 0) {
num = Math.DivRem(num, 10, out rm);
res = res * 10 + rm;
}
return res ;
}
Making the method return a bool was slightly slower than comparing to a bool in a loop in my computer, but I don't understand why. Please test in your computer.
Multiplication and bit-shifing should be faster than division but probably are not precise enough. EDIT: using long seems be precise enough.
private static int FastReverse(int num) {
int res = 0;
int q = (int)((214748365L * num) >> 31);
int rm = num - 10 * q;
num = q;
if (rm == 0) return -1;
res = res * 10 + rm;
while (num > 0) {
q = (int)((214748365L * num) >> 31);
rm = num - 10 * q;
num = q;
res = res * 10 + rm;
}
return res;
}
(214748365L * num) >> 31 is equal to i / 10 until 1,073,741,829 where 1 / 10 gives 107374182 and the multiplication + binary shifting gives 107374183.
I think it might be faster to do the comparison in-place. If you reverse the string, you've got to:
Instantiate a new string object (or StringBuffer object)
Copy the data (in reverse) from the first string to the new string
Do your comparison.
If you perform the comparison in place, you do only the last step. An even then, your comparison is only half the string (or half - 0.5, in the event of an odd number of characters). Something like the following should work:
static bool IsPalindromic(string s){
int len = s.Length;
int half = len-- >> 1;
for(int i = 0; i < half; i++)
if(s[i] != s[len - i])
return false;
return true;
}
EDIT:
Although this answers the OP's question, the solutions offered by ggf31416 and configurator solve the OP's real need about 30% faster, by my tests. configurator's solution is a tiny bit faster than ggf31416's, if you convert it to a static method and use ints instead of ulongs (but much slower, otherwise).
Incidentally, running through these examples to solve the problem the OP mentions (finding the largest palindromic product of any two three-digit numbers) with the simple (perhaps naïve) loop below:
for(int i = 100; i < 1000; i++)
for(int j = i; j < 1000; j++) // calculations where j < i would be redundant
...
yields the following results on my machine:
IsPalindromic(product.ToString()) took 0.3064174 seconds.
ggf31416Reverse(product) == product took 0.1933994 seconds.
configuratorReverse(product) == product took 0.1872061 seconds.
Each produces the correct result of 913 * 993 = 906609.
Performance: Fastest string reversing algorithms... (final results)
string test = "ABC";
string reversed = new String(test.ToCharArray().Reverse().ToArray());
public static String Reverse(string input) {
var length = input.Length;
var buffer = new char[length];
for ( var i= 0; i < input.Length; i++ ) {
buffer[i] = input[(length-i)-1];
}
return new String(buffer);
}
EDIT: Doh! Forgot to halve the length for perf :)
The fastest way I have found to reverse a string in C# is with the following code. It's faster reading in 32bits at a time instead of a char's length of 16bits.
In debug mode, it is faster until you get to about 93 characters. Anything longer than that Array.Reverse() is faster. Using a release build and running outside of the IDE, this method will blow Array.Reverse() out of the water at any string length.
char[] MyCharArray = MyString.ToCharArray();
UIntStringReverse(ref MyCharArray); //Code to reverse is below.
string ReversedString = new string(MyCharArray);
private static unsafe void UIntStringReverse(ref char[] arr)
{
uint Temp;
uint Temp2;
fixed (char* arrPtr = &arr[0])
{
uint* p, q;
p = (uint*)(arrPtr);
q = (uint*)(arrPtr + arr.LongLength - 2);
if (arr.LongLength == 2)
{
Temp = *p;
*p = ((Temp & 0xFFFF0000) >> 16) | ((Temp & 0x0000FFFF) << 16);
return;
}
while (p < q)
{
Temp = *p;
Temp2 = *q;
*p = ((Temp2 & 0xFFFF0000) >> 16) | ((Temp2 & 0x0000FFFF) << 16);
*q = ((Temp & 0xFFFF0000) >> 16) | ((Temp & 0x0000FFFF) << 16);
p++;
q--;
}
}
}
try this too:
http://weblogs.sqlteam.com/mladenp/archive/2006/03/19/9350.aspx
string Reverse(string s)
{
return new string(s.ToCharArray().Reverse().ToArray());
}
Using ggf31416's FastReverse function, here is the solution to Project Euler's Problem #4 which completes on my computer in 47ms.
using System;
using System.Diagnostics;
namespace Euler_Problem_4
{
class Program
{
static void Main(string[] args)
{
Stopwatch s = new Stopwatch();
s.Start();
int t = 0;
for (int i = 999; i > 99; i--)
{
for (int j = i; j > 99; j--)
{
if (i*j == FastReverse(i*j))
{
if (i * j > t)
{
t = i * j;
}
}
}
}
Console.WriteLine(t);
s.Stop();
Console.WriteLine("{0}mins {1}secs {2}ms", s.Elapsed.Minutes, s.Elapsed.Seconds, s.Elapsed.Milliseconds);
Console.ReadKey(true);
}
private static int FastReverse(int num)
{
int res = 0;
int q = (int)((214748365L * num) >> 31);
int rm = num - 10 * q;
num = q;
if (rm == 0) return -1;
res = res * 10 + rm;
while (num > 0)
{
q = (int)((214748365L * num) >> 31);
rm = num - 10 * q;
num = q;
res = res * 10 + rm;
}
return res;
}
}
}
The Stopwatch class needs reset after each run. the code below has been corrected
var d = s.ToCharArray();
Array.Reverse(d);
return s == new string(d);
using System;
using System.Diagnostics;
namespace longeststring_codegolf
{
class Program
{
static void Main(string[] args)
{
int t = 0, v = 0;
var sw = new Stopwatch();
sw.Start();
for (int i = 999; i > 99; i--)
for (int j = 999; j > 99; j--)
if ((v = i * j) > t && IsPalindromicMine(v.ToString()))
t = v;
sw.Stop();
var elapsed = sw.Elapsed;
var elapsedMilliseconds = sw.ElapsedMilliseconds;
var elapsedTicks = sw.ElapsedTicks;
Console.WriteLine("Ticks: " + elapsedTicks.ToString());//~189000
Console.WriteLine("Milliseconds: " + elapsedMilliseconds.ToString()); //~9
sw = Stopwatch.StartNew();
for (int i = 999; i > 99; i--)
for (int j = 999; j > 99; j--)
if ((v = i * j) > t && IsPalindromic(v.ToString()))
t = v;
sw.Stop();
var elapsed2 = sw.Elapsed;
var elapsedMilliseconds2 = sw.ElapsedMilliseconds;
var elapsedTicks2 = sw.ElapsedTicks;
Console.WriteLine("Ticks: " + elapsedTicks2.ToString());//~388000
Console.WriteLine("Milliseconds: " + elapsedMilliseconds2.ToString());//~20
}
static bool IsPalindromicMine(string s)
{
var d = s.ToCharArray();
Array.Reverse(d);
return s == new string(d);
}
static bool IsPalindromic(string s)
{
int len = s.Length;
int half = len-- >> 1;
for (int i = 0; i < half; i++)
if (s[i] != s[len - i])
return false;
return true;
}
}
}