Related
I have the following hash function, and I'm trying to get my way to reverse it, so that I can find the key from a hashed value.
uint Hash(string s)
{
uint result = 0;
for (int i = 0; i < s.Length; i++)
{
result = ((result << 5) + result) + s[i];
}
return result;
}
The code is in C# but I assume it is clear.
I am aware that for one hashed value, there can be more than one key, but my intent is not to find them all, just one that satisfies the hash function suffices.
EDIT :
The string that the function accepts is formed only from digits 0 to 9 and the chars '*' and '#' hence the Unhash function must respect this criteria too.
Any ideas? Thank you.
This should reverse the operations:
string Unhash(uint hash)
{
List<char> s = new List<char>();
while (hash != 0)
{
s.Add((char)(hash % 33));
hash /= 33;
}
s.Reverse();
return new string(s.ToArray());
}
This should return a string that gives the same hash as the original string, but it is very unlikely to be the exact same string.
Characters 0-9,*,# have ASCII values 48-57,42,35, or binary: 00110000 ... 00111001, 00101010, 00100011
First 5 bits of those values are different, and 6th bit is always 1. This means that you can deduce your last character in a loop by taking current hash:
uint lastChar = hash & 0x1F - ((hash >> 5) - 1) & 0x1F + 0x20;
(if this doesn't work, I don't know who wrote it)
Now roll back hash,
hash = (hash - lastChar) / 33;
and repeat the loop until hash becomes zero. I don't have C# on me, but I'm 70% confident that this should work with only minor changes.
Brute force should work if uint is 32 bits. Try at least 2^32 strings and one of them is likely to hash to the same value. Should only take a few minutes on a modern pc.
You have 12 possible characters, and 12^9 is about 2^32, so if you try 9 character strings you're likely to find your target hash. I'll do 10 character strings just to be safe.
(simple recursive implementation in C++, don't know C# that well)
#define NUM_VALID_CHARS 12
#define STRING_LENGTH 10
const char valid_chars[NUM_VALID_CHARS] = {'0', ..., '#' ,'*'};
void unhash(uint hash_value, char *string, int nchars) {
if (nchars == STRING_LENGTH) {
string[STRING_LENGTH] = 0;
if (Hash(string) == hash_value) { printf("%s\n", string); }
} else {
for (int i = 0; i < NUM_VALID_CHARS; i++) {
string[nchars] = valid_chars[i];
unhash(hash_value, string, nchars + 1);
}
}
}
Then call it with:
char string[STRING_LENGTH + 1];
unhash(hash_value, string, 0);
Hash functions are designed to be difficult or impossible to reverse, hence the name (visualize meat + potatoes being ground up)
I would start out by writing each step that result = ((result << 5) + result) + s[i]; does on a separate line. This will make solving a lot easier. Then all you have to do is the opposite of each line (in the opposite order too).
Assuming the 64bit integer 0x000000000000FFFF which would be represented as
00000000 00000000 00000000 00000000
00000000 00000000 >11111111 11111111
How do I find the amount of unset bits to the left of the most significant set bit (the one marked with >) ?
In straight C (long long are 64 bit on my setup), taken from similar Java implementations: (updated after a little more reading on Hamming weight)
A little more explanation: The top part just sets all bit to the right of the most significant 1, and then negates it. (i.e. all the 0's to the 'left' of the most significant 1 are now 1's and everything else is 0).
Then I used a Hamming Weight implementation to count the bits.
unsigned long long i = 0x0000000000000000LLU;
i |= i >> 1;
i |= i >> 2;
i |= i >> 4;
i |= i >> 8;
i |= i >> 16;
i |= i >> 32;
// Highest bit in input and all lower bits are now set. Invert to set the bits to count.
i=~i;
i -= (i >> 1) & 0x5555555555555555LLU; // each 2 bits now contains a count
i = (i & 0x3333333333333333LLU) + ((i >> 2) & 0x3333333333333333LLU); // each 4 bits now contains a count
i = (i + (i >> 4)) & 0x0f0f0f0f0f0f0f0fLLU; // each 8 bits now contains a count
i *= 0x0101010101010101LLU; // add each byte to all the bytes above it
i >>= 56; // the number of bits
printf("Leading 0's = %lld\n", i);
I'd be curious to see how this was efficiency wise. Tested it with several values though and it seems to work.
Based on: http://www.hackersdelight.org/HDcode/nlz.c.txt
template<typename T> int clz(T v) {int n=sizeof(T)*8;int c=n;while (n){n>>=1;if (v>>n) c-=n,v>>=n;}return c-v;}
If you'd like a version that allows you to keep your lunch down, here you go:
int clz(uint64_t v) {
int n=64,c=64;
while (n) {
n>>=1;
if (v>>n) c-=n,v>>=n;
}
return c-v;
}
As you'll see, you can save cycles on this by careful analysis of the assembler, but the strategy here is not a terrible one. The while loop will operate Lg[64]=6 times; each time it will convert the problem into one of counting the number of leading bits on an integer of half the size.
The if statement inside the while loop asks the question: "can i represent this integer in half as many bits", or analogously, "if i cut this in half, have i lost it?". After the if() payload completes, our number will always be in the lowest n bits.
At the final stage, v is either 0 or 1, and this completes the calculation correctly.
If you are dealing with unsigned integers, you could do this:
#include <math.h>
int numunset(uint64_t number)
{
int nbits = sizeof(uint64_t)*8;
if(number == 0)
return nbits;
int first_set = floor(log2(number));
return nbits - first_set - 1;
}
I don't know how it will compare in performance to the loop and count methods that have already been offered because log2() could be expensive.
Edit:
This could cause some problems with high-valued integers since the log2() function is casting to double and some numerical issues may arise. You could use the log2l() function that works with long double. A better solution would be to use an integer log2() function as in this question.
// clear all bits except the lowest set bit
x &= -x;
// if x==0, add 0, otherwise add x - 1.
// This sets all bits below the one set above to 1.
x+= (-(x==0))&(x - 1);
return 64 - count_bits_set(x);
Where count_bits_set is the fastest version of counting bits you can find. See https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel for various bit counting techniques.
I'm not sure I understood the problem correctly. I think you have a 64bit value and want to find the number of leading zeros in it.
One way would be to find the most significant bit and simply subtract its position from 63 (assuming lowest bit is bit 0). You can find out the most significant bit by testing whether a bit is set from within a loop over all 64 bits.
Another way might be to use the (non-standard) __builtin_clz in gcc.
I agree with the binary search idea. However two points are important here:
The range of valid answers to your question is from 0 to 64 inclusive. In other words - there may be 65 different answers to the question. I think (almost sure) all who posted the "binary search" solution missed this point, hence they'll get wrong answer for either zero or a number with the MSB bit on.
If speed is critical - you may want to avoid the loop. There's an elegant way to achieve this using templates.
The following template stuff finds the MSB correctly of any unsigned type variable.
// helper
template <int bits, typename T>
bool IsBitReached(T x)
{
const T cmp = T(1) << (bits ? (bits-1) : 0);
return (x >= cmp);
}
template <int bits, typename T>
int FindMsbInternal(T x)
{
if (!bits)
return 0;
int ret;
if (IsBitReached<bits>(x))
{
ret = bits;
x >>= bits;
} else
ret = 0;
return ret + FindMsbInternal<bits/2, T>(x);
}
// Main routine
template <typename T>
int FindMsb(T x)
{
const int bits = sizeof(T) * 8;
if (IsBitReached<bits>(x))
return bits;
return FindMsbInternal<bits/2>(x);
}
Here you go, pretty trivial to update as you need for other sizes...
int bits_left(unsigned long long value)
{
static unsigned long long mask = 0x8000000000000000;
int c = 64;
// doh
if (value == 0)
return c;
// check byte by byte to see what has been set
if (value & 0xFF00000000000000)
c = 0;
else if (value & 0x00FF000000000000)
c = 8;
else if (value & 0x0000FF0000000000)
c = 16;
else if (value & 0x000000FF00000000)
c = 24;
else if (value & 0x00000000FF000000)
c = 32;
else if (value & 0x0000000000FF0000)
c = 40;
else if (value & 0x000000000000FF00)
c = 48;
else if (value & 0x00000000000000FF)
c = 56;
// skip
value <<= c;
while(!(value & mask))
{
value <<= 1;
c++;
}
return c;
}
Same idea as user470379's, but counting down ...
Assume all 64 bits are unset. While value is larger than 0 keep shifting the value right and decrementing number of unset bits:
/* untested */
int countunsetbits(uint64_t val) {
int x = 64;
while (val) { x--; val >>= 1; }
return x;
}
Try
int countBits(int value)
{
int result = sizeof(value) * CHAR_BITS; // should be 64
while(value != 0)
{
--result;
value = value >> 1; // Remove bottom bits until all 1 are gone.
}
return result;
}
Use log base 2 to get you the most significant digit which is 1.
log(2) = 1, meaning 0b10 -> 1
log(4) = 2, 5-7 => 2.xx, or 0b100 -> 2
log(8) = 3, 9-15 => 3.xx, 0b1000 -> 3
log(16) = 4 you get the idea
and so on...
The numbers in between become fractions of the log result. So typecasting the value to an int gives you the most significant digit.
Once you get this number, say b, the simple 64 - n will be the answer.
function get_pos_msd(int n){
return int(log2(n))
}
last_zero = 64 - get_pos_msd(n)
There is a function in the AES algorithm, to multiply a byte by 2 in Galois Field.
This is the function given in a website
private static byte gfmultby02(byte b)
{
if (b < 0x80)
return (byte)(int)(b <<1);
else
return (byte)( (int)(b << 1) ^ (int)(0x1b) );
}
This is the function i wrote.
private static byte MulGF2(byte x)
{
if (x < 0x80)
return (byte)(x << 1);
else
{
return (byte)((x << 1) ^ 0x1b);
}
}
What i need to know is, given any byte whether this will perform in the same manner. Actually I am worried about the extra cast to int and then again to byte. So far I have tested and it looks fine. Does the extra cast to int and then to byte make a difference in rare cases?
I think in this case the cast to int does nothing, cause the cast is done after the left shift. So let's take a little example:
byte b = 0x1000;
//temp1 == 0x00000000;
int temp1 = (int)(b << 1);
//temp2 == 0x00010000;
int temp2 = ((int)b) << 1);
So as you can see the parentheses have a big impact on the result, but if took the formula from the website right, your code should behave the same.
I think it's correct, but:
The best way to make sure is to simply test it; there are only 256 cases and it shouldn't take many minutes to write the test case.
I'd like to be able to swap two variables without the use of a temporary variable in C#. Can this be done?
decimal startAngle = Convert.ToDecimal(159.9);
decimal stopAngle = Convert.ToDecimal(355.87);
// Swap each:
// startAngle becomes: 355.87
// stopAngle becomes: 159.9
C# 7 introduced tuples which enables swapping two variables without a temporary one:
int a = 10;
int b = 2;
(a, b) = (b, a);
This assigns b to a and a to b.
The right way to swap two variables (at the time this question was asked(1)) is:
decimal tempDecimal = startAngle;
startAngle = stopAngle;
stopAngle = tempDecimal;
In other words, use a temporary variable.
There you have it. No clever tricks, no maintainers of your code cursing you for decades to come, no entries to The Daily WTF, and no spending too much time trying to figure out why you needed it in one operation anyway since, at the lowest level, even the most complicated language feature is a series of simple operations.
Just a very simple, readable, easy to understand, t = a; a = b; b = t; solution.
In my opinion, developers who try to use tricks to, for example, "swap variables without using a temp" or "Duff's device" are just trying to show how clever they are (and failing miserably).
I liken them to those who read highbrow books solely for the purpose of seeming more interesting at parties (as opposed to expanding your horizons).
Solutions where you add and subtract, or the XOR-based ones, are less readable and most likely slower than a simple "temp variable" solution (arithmetic/boolean-ops instead of plain moves at an assembly level).
Do yourself, and others, a service by writing good quality readable code.
That's my rant. Thanks for listening :-)
As an aside, I'm quite aware this doesn't answer your specific question (and I'll apologise for that) but there's plenty of precedent on SO where people have asked how to do something and the correct answer is "Don't do it".
(1) Improvements to the language and/or .NET Core since that time have adopted the "Pythonic" way using tuples. Now you can just do:
(startAngle, stopAngle) = (stopAngle, startAngle);
to swap values.
First of all, swapping without a temporary variable in a language as C# is a very bad idea.
But for the sake of answer, you can use this code:
startAngle = startAngle + stopAngle;
stopAngle = startAngle - stopAngle;
startAngle = startAngle - stopAngle;
Problems can however occur with rounding off if the two numbers differ largely. This is due to the nature of floating point numbers.
If you want to hide the temporary variable, you can use a utility method:
public static class Foo {
public static void Swap<T> (ref T lhs, ref T rhs) {
T temp = lhs;
lhs = rhs;
rhs = temp;
}
}
Yes, use this code:
stopAngle = Convert.ToDecimal(159.9);
startAngle = Convert.ToDecimal(355.87);
The problem is harder for arbitrary values. :-)
int a = 4, b = 6;
a ^= b ^= a ^= b;
Works for all types including strings and floats.
BenAlabaster showed a practical way of doing a variable switch, but the try-catch clause is not needed. This code is enough.
static void Swap<T>(ref T x, ref T y)
{
T t = y;
y = x;
x = t;
}
The usage is the same as he shown:
float startAngle = 159.9F
float stopAngle = 355.87F
Swap(ref startAngle, ref stopAngle);
You could also use an extension method:
static class SwapExtension
{
public static T Swap<T>(this T x, ref T y)
{
T t = y;
y = x;
return t;
}
}
Use it like this:
float startAngle = 159.9F;
float stopAngle = 355.87F;
startAngle = startAngle.Swap(ref stopAngle);
Both ways uses a temporary variable in the method, but you don't need the temporary variable where you do the swapping.
A binary XOR swap with a detailed example:
XOR truth table:
a b a^b
0 0 0
0 1 1
1 0 1
1 1 0
Input:
a = 4;
b = 6;
Step 1: a = a ^ b
a : 0100
b : 0110
a^b: 0010 = 2 = a
Step 2: b = a ^ b
a : 0010
b : 0110
a^b: 0100 = 4 = b
Step 3: a = a ^ b
a : 0010
b : 0100
a^b: 0110 = 6 = a
Output:
a = 6;
b = 4;
In C# 7:
(startAngle, stopAngle) = (stopAngle, startAngle);
Not in C#. In native code you might be able to use the triple-XOR swap trick, but not in a high level type-safe language. (Anyway, I've heard that the XOR trick actually ends up being slower than using a temporary variable in many common CPU architectures.)
You should just use a temporary variable. There's no reason you can't use one; it's not like there's a limited supply.
For the sake of future learners, and humanity, I submit this correction to the currently selected answer.
If you want to avoid using temp variables, there are only two sensible options that take first performance and then readability into consideration.
Use a temp variable in a generic Swap method. (Absolute best performance, next to inline temp variable)
Use Interlocked.Exchange. (5.9 times slower on my machine, but this is your only option if multiple threads will be swapping these variables simultaneously.)
Things you should never do:
Never use floating point arithmetic. (slow, rounding and overflow errors, hard to understand)
Never use non-primitive arithmetic. (slow, overflow errors, hard to understand) Decimal is not a CPU primitive and results in far more code than you realize.
Never use arithmetic period. Or bit hacks. (slow, hard to understand) That's the compiler's job. It can optimize for many different platforms.
Because everyone loves hard numbers, here's a program that compares your options. Run it in release mode from outside Visual Studio so that Swap is inlined. Results on my machine (Windows 7 64-bit i5-3470):
Inline: 00:00:00.7351931
Call: 00:00:00.7483503
Interlocked: 00:00:04.4076651
Code:
class Program
{
static void Swap<T>(ref T obj1, ref T obj2)
{
var temp = obj1;
obj1 = obj2;
obj2 = temp;
}
static void Main(string[] args)
{
var a = new object();
var b = new object();
var s = new Stopwatch();
Swap(ref a, ref b); // JIT the swap method outside the stopwatch
s.Restart();
for (var i = 0; i < 500000000; i++)
{
var temp = a;
a = b;
b = temp;
}
s.Stop();
Console.WriteLine("Inline temp: " + s.Elapsed);
s.Restart();
for (var i = 0; i < 500000000; i++)
{
Swap(ref a, ref b);
}
s.Stop();
Console.WriteLine("Call: " + s.Elapsed);
s.Restart();
for (var i = 0; i < 500000000; i++)
{
b = Interlocked.Exchange(ref a, b);
}
s.Stop();
Console.WriteLine("Interlocked: " + s.Elapsed);
Console.ReadKey();
}
}
<deprecated>
You can do it in 3 lines using basic math - in my example I used multiplication, but simple addition would work also.
float startAngle = 159.9F;
float stopAngle = 355.87F;
startAngle = startAngle * stopAngle;
stopAngle = startAngle / stopAngle;
startAngle = startAngle / stopAngle;
Edit: As noted in the comments, this wouldn't work if y = 0 as it would generate a divide by zero error which I hadn't considered. So the +/- solution alternatively presented would be the best way to go.
</deprecated>
To keep my code immediately comprehensible, I'd be more likely to do something like this. [Always think about the poor guy that's gonna have to maintain your code]:
static bool Swap<T>(ref T x, ref T y)
{
try
{
T t = y;
y = x;
x = t;
return true;
}
catch
{
return false;
}
}
And then you can do it in one line of code:
float startAngle = 159.9F
float stopAngle = 355.87F
Swap<float>(ref startAngle, ref stopAngle);
Or...
MyObject obj1 = new MyObject("object1");
MyObject obj2 = new MyObject("object2");
Swap<MyObject>(ref obj1, ref obj2);
Done like dinner...you can now pass in any type of object and switch them around...
With C# 7, you can use tuple deconstruction to achieve the desired swap in one line, and it's clear what's going on.
decimal startAngle = Convert.ToDecimal(159.9);
decimal stopAngle = Convert.ToDecimal(355.87);
(startAngle, stopAngle) = (stopAngle, startAngle);
For completeness, here is the binary XOR swap:
int x = 42;
int y = 51236;
x ^= y;
y ^= x;
x ^= y;
This works for all atomic objects/references, as it deals directly with the bytes, but may require an unsafe context to work on decimals or, if you're feeling really twisted, pointers. And it may be slower than a temp variable in some circumstances as well.
If you can change from using decimal to double you can use the Interlocked class.
Presumably this will be a good way of swapping variables performance wise. Also slightly more readable than XOR.
var startAngle = 159.9d;
var stopAngle = 355.87d;
stopAngle = Interlocked.Exchange(ref startAngle, stopAngle);
Msdn: Interlocked.Exchange Method (Double, Double)
a = a + b
b = a - b
a = a - b
َ
Beware of your environment!
For example, this doesn’t seem to work in ECMAscript
y ^= x ^= y ^= x;
But this does
x ^= y ^= x; y ^= x;
My advise? Assume as little as possible.
The simple way to swap 2 numbers in just one line:
a=(a+b)-(b=a);
eg: a=1, b=2
Step 1: a=(1+2) - (b=1)
Step 2: a=3-1
=> a=2 and b=1
Efficient way is to use:
C Programming: (x ^= y), (y ^= x), (x ^= y);
Java: x = x ^ y ^ (y = x);
Python: x, y = y, x
Note: Most common mistake people make:
//Swap using bitwise XOR (Wrong Solution in C/C++)
x ^= y ^= x ^= y;
Source: GeeksforGeek
For binary types you can use this funky trick:
a %= b %= a %= b;
As long as a and b are not the exact same variable (e.g. aliases for the same memory) it works.
I hope this might help...
using System;
public class Program
{
public static void Main()
{
int a = 1234;
int b = 4321;
Console.WriteLine("Before: a {0} and b {1}", a, b);
b = b - a;
a = a + b;
b = a - b;
Console.WriteLine("After: a {0} and b {1}", a, b);
}
}
we can do that by doing a simple trick
a = 20;
b = 30;
a = a+b; // add both the number now a has value 50
b = a-b; // here we are extracting one number from the sum by sub
a = a-b; // the number so obtained in above help us to fetch the alternate number from sum
System.out.print("swapped numbers are a = "+ a+"b = "+ b);
Sometimes I wish it were possible to write a function in MSIL inline in C#, similar to how you can write inline assembler in C.
For the record, I once wrote a helper library for C# with various functions for things that were impossible to write in C# but can be written in MSIL (non-zero-based arrays for example). I had this function:
.method public hidebysig static void Swap<T> (
!!T& a,
!!T& b
) cil managed
{
.maxstack 4
ldarg.1 // push a& reference
ldarg.2 // push b& reference
ldobj !!T // pop b&, push b
ldarg.2 // push b& reference
ldarg.1 // push a& reference
ldobj !!T // pop a&, push a
stobj !!T // store a in b&
stobj !!T // store b in a&
ret
}
And no locals needed. Of course this was just me being silly...
startAngle = (startAngle + stopAngle) - (stopAngle = startAngle);
If you want to swap 2 string variables:
a = (a+b).Substring((b=a).Length);
An helper method accordingly:
public static class Foo {
public static void SwapString (ref string a, ref string b) {
a = (a+b).Substring((b=a).Length);
}
}
Usage would be then:
string a="Test 1";
string b="Test 2";
Foo.SwapString(a, b);
Here another approach in one line:
decimal a = 159.9m;
decimal b = 355.87m;
a = b + (b = a) - b;
Here is some different process to swap two variables
//process one
a=b+a;
b=a-b;
a=a-b;
printf("a= %d b= %d",a,b);
//process two
a=5;
b=10;
a=a+b-(b=a);
printf("\na= %d b= %d",a,b);
//process three
a=5;
b=10;
a=a^b;
b=a^b;
a=b^a;
printf("\na= %d b= %d",a,b);
//process four
a=5;
b=10;
a=b-~a-1;
b=a+~b+1;
a=a+~b+1;
printf("\na= %d b= %d",a,b);
this model is very useful
var a = 10;
var b = 20;
(int a,int b) c = (a,b);
a = c.b ;
b = c.a ;
var a = 15;
var b = -214;
a = b | !(b = a);
This works great.
Very simple code for swapping two variables:
static void Main(string[] args)
{
Console.WriteLine("Prof.Owais ahmed");
Console.WriteLine("Swapping two variables");
Console.WriteLine("Enter your first number ");
int x = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("Enter your first number ");
int y = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("your vlaue of x is="+x+"\nyour value of y is="+y);
int z = x;
x = y;
y = z;
Console.WriteLine("after Swapping value of x is="+x+"/nyour value of y is="+y);
Console.ReadLine();
}
You can try the following code. It is much more better than the other code.
a = a + b;
b = a - b;
a = a - b;
I have a char in c#:
char foo = '2';
Now I want to get the 2 into an int. I find that Convert.ToInt32 returns the actual decimal value of the char and not the number 2. The following will work:
int bar = Convert.ToInt32(new string(foo, 1));
int.parse only works on strings as well.
Is there no native function in C# to go from a char to int without making it a string? I know this is trivial but it just seems odd that there's nothing native to directly make the conversion.
This will convert it to an int:
char foo = '2';
int bar = foo - '0';
This works because each character is internally represented by a number. The characters '0' to '9' are represented by consecutive numbers, so finding the difference between the characters '0' and '2' results in the number 2.
Interesting answers but the docs say differently:
Use the GetNumericValue methods to
convert a Char object that represents
a number to a numeric value type. Use
Parse and TryParse to convert a
character in a string into a Char
object. Use ToString to convert a Char
object to a String object.
http://msdn.microsoft.com/en-us/library/system.char.aspx
Has anyone considered using int.Parse() and int.TryParse() like this
int bar = int.Parse(foo.ToString());
Even better like this
int bar;
if (!int.TryParse(foo.ToString(), out bar))
{
//Do something to correct the problem
}
It's a lot safer and less error prone
char c = '1';
int i = (int)(c - '0');
and you can create a static method out of it:
static int ToInt(this char c)
{
return (int)(c - '0');
}
Try This
char x = '9'; // '9' = ASCII 57
int b = x - '0'; //That is '9' - '0' = 57 - 48 = 9
By default you use UNICODE so I suggest using faulty's method
int bar = int.Parse(foo.ToString());
Even though the numeric values under are the same for digits and basic Latin chars.
This converts to an integer and handles unicode
CharUnicodeInfo.GetDecimalDigitValue('2')
You can read more here.
The real way is:
int theNameOfYourInt = (int).Char.GetNumericValue(theNameOfYourChar);
"theNameOfYourInt" - the int you want your char to be transformed to.
"theNameOfYourChar" - The Char you want to be used so it will be transformed into an int.
Leave everything else be.
Principle:
char foo = '2';
int bar = foo & 15;
The binary of the ASCII charecters 0-9 is:
0 - 0011 0000
1 - 0011 0001
2 - 0011 0010
3 - 0011 0011
4 - 0011 0100
5 - 0011 0101
6 - 0011 0110
7 - 0011 0111
8 - 0011 1000
9 - 0011 1001
and if you take in each one of them the first 4 LSB (using bitwise AND with 8'b00001111 that equals to 15) you get the actual number (0000 = 0,0001=1,0010=2,... )
Usage:
public static int CharToInt(char c)
{
return 0b0000_1111 & (byte) c;
}
I am agree with #Chad Grant
Also right if you convert to string then you can use that value as numeric as said in the question
int bar = Convert.ToInt32(new string(foo, 1)); // => gives bar=2
I tried to create a more simple and understandable example
char v = '1';
int vv = (int)char.GetNumericValue(v);
char.GetNumericValue(v) returns as double and converts to (int)
More Advenced usage as an array
int[] values = "41234".ToArray().Select(c=> (int)char.GetNumericValue(c)).ToArray();
First convert the character to a string and then convert to integer.
var character = '1';
var integerValue = int.Parse(character.ToString());
I'm using Compact Framework 3.5, and not has a "char.Parse" method.
I think is not bad to use the Convert class. (See CLR via C#, Jeffrey Richter)
char letterA = Convert.ToChar(65);
Console.WriteLine(letterA);
letterA = 'あ';
ushort valueA = Convert.ToUInt16(letterA);
Console.WriteLine(valueA);
char japaneseA = Convert.ToChar(valueA);
Console.WriteLine(japaneseA);
Works with ASCII char or Unicode char
Comparison of some of the methods based on the result when the character is not an ASCII digit:
char c1 = (char)('0' - 1), c2 = (char)('9' + 1);
Debug.Print($"{c1 & 15}, {c2 & 15}"); // 15, 10
Debug.Print($"{c1 ^ '0'}, {c2 ^ '0'}"); // 31, 10
Debug.Print($"{c1 - '0'}, {c2 - '0'}"); // -1, 10
Debug.Print($"{(uint)c1 - '0'}, {(uint)c2 - '0'}"); // 4294967295, 10
Debug.Print($"{char.GetNumericValue(c1)}, {char.GetNumericValue(c2)}"); // -1, -1
I was searched for the most optimized method and was very surprized that the best is the easiest (and the most popular answer):
public static int ToIntT(this char c) =>
c is >= '0' and <= '9'?
c-'0' : -1;
There a list of methods I tried:
c-'0' //current
switch //about 25% slower, no method with disabled isnum check (it is but performance is same as with enabled)
0b0000_1111 & (byte) c; //same speed
Uri.FromHex(c) /*2 times slower; about 20% slower if use my isnum check*/ (c is >= '0' and <= '9') /*instead of*/ Uri.IsHexDigit(testChar)
(int)char.GetNumericValue(c); // about 20% slower. I expected it will be much more slower.
Convert.ToInt32(new string(c, 1)) //3-4 times slower
Note that isnum check (2nd line in the first codeblock) takes ~30% of perfomance, so you should take it off if you sure that c is char. The testing error was ~5%
Use this:
public static string NormalizeNumbers(this string text)
{
if (string.IsNullOrWhiteSpace(text)) return text;
string normalized = text;
char[] allNumbers = text.Where(char.IsNumber).Distinct().ToArray();
foreach (char ch in allNumbers)
{
char equalNumber = char.Parse(char.GetNumericValue(ch).ToString("N0"));
normalized = normalized.Replace(ch, equalNumber);
}
return normalized;
}
One very quick simple way just to convert chars 0-9 to integers:
C# treats a char value much like an integer.
char c = '7'; (ascii code 55) int x = c - 48; (result = integer of 7)
Use Uri.FromHex.
And to avoid exceptions Uri.IsHexDigit.
char testChar = 'e';
int result = Uri.IsHexDigit(testChar)
? Uri.FromHex(testChar)
: -1;
I prefer the switch method.
The performance is the same as c - '0' but I find the switch easier to read.
Benchmark:
Method
Mean
Error
StdDev
Allocated Memory/Op
CharMinus0
90.24 us
7.1120 us
0.3898 us
39.18 KB
CharSwitch
90.54 us
0.9319 us
0.0511 us
39.18 KB
Code:
public static int CharSwitch(this char c, int defaultvalue = 0) {
switch (c) {
case '0': return 0;
case '1': return 1;
case '2': return 2;
case '3': return 3;
case '4': return 4;
case '5': return 5;
case '6': return 6;
case '7': return 7;
case '8': return 8;
case '9': return 9;
default: return defaultvalue;
}
}
public static int CharMinus0(this char c, int defaultvalue = 0) {
return c >= '0' && c <= '9' ? c - '0' : defaultvalue;
}
This worked for me:
int bar = int.Parse("" + foo);
I've seen many answers but they seem confusing to me. Can't we just simply use Type Casting.
For ex:-
int s;
char i= '2';
s = (int) i;