There's a similar question asked and answered in C, but I'm struggling a bit to achieve the same thing in C#.
Generator Polynomial : x^16 + x^10 + x^8 + x^7 + x^3 + 1 which is equivalent to 10000010110001001 in binary.
I have 48 bits of data, and now I required to generate 16 bits of CRC, here's the code:
private bool[] MakeCRC(string BitString)
{
bool[] Res = new bool[17];
bool[] CRC = new bool[16];
int i;
bool DoInvert= false;
for (i = 0; i < 16; ++i) // Init before calculation
CRC[i] = false;
for (i = 0; i < BitString.Length; ++i)
{
if (BitString[i] == '1')
DoInvert = true ^ CRC[15];
//DoInvert = ('1' == BitString[i]) ^ CRC[15]; // XOR required?
CRC[15] = CRC[14];
CRC[14] = CRC[13];
CRC[13] = CRC[12];
CRC[12] = CRC[11];
CRC[11] = CRC[10];
CRC[10] = CRC[9] ^ DoInvert;
CRC[9] = CRC[8];
CRC[8] = CRC[7] ^ DoInvert;
CRC[7] = CRC[6] ^ DoInvert;
CRC[6] = CRC[5];
CRC[5] = CRC[4];
CRC[4] = CRC[3];
CRC[3] = CRC[2] ^ DoInvert;
CRC[2] = CRC[1];
CRC[1] = CRC[0];
CRC[0] = DoInvert;
}
for (i = 0; i < 16; ++i)
Res[15 - i] = CRC[i] ? true : false;
Res[16] = false; // Set string terminator
return (Res);
}
but the above code, gives me wrong output, please suggest me if there's any better way of doing it.
Edit:
Data(a0 to a47): 100011100011000001000001000100001000000000001000
Polynomial: 10000010110001001
Output Obtained: 0011 0100 1111 0111
Output Expected: 1100 1101 0100 1111
Thanks for your time.!
uncomment DoInvert = ('1' == BitString[i]) ^ CRC[15];
and remove the line above and it works.
Your replacement for the commented line is wrong. Right would be:
if (BitString[i] == '1')
DoInvert = true ^ CRC[15];
else
DoInvert = false ^ CRC[15];
Related
The (wireless) mBus standard uses a number as equivalent to a manufacturer-string. Some examples are shown here: https://www.m-bus.de/man.html
Turning a manufacturer string like "IST" to the correct number 0x2674 is explained on the website for javascript, I turned it successfully into a c# function:
public static bool TryMANtoHEX(string man_str, out uint man_hex)
{
man_hex = 0;
if (man_str.Length != 3) return false;
if (!Regex.IsMatch(man_str, #"^[a-zA-Z]+$")) return false;
man_str = man_str.ToUpper();
try
{
man_hex += ((uint)man_str[2] - 64);
man_hex += ((uint)man_str[1] - 64) * 32;
man_hex += ((uint)man_str[0] - 64) * 32 * 32;
} catch
{
return false;
}
return true;
}
But I am struggling to revert this function, so turning an number back to a string.
I tried the following code an it works for character 1 and 3 - but not for char 2:
public static bool TryHEXtoMAN(uint man_hex, out string man_str)
{
man_str = string.Empty;
char c1 = (char)((man_hex / 1024) + 64);
char c2 = (char)((man_hex / 32) + 64);
char c3 = (char)((man_hex % 32) + 64);
char[] cs = { c1, c2, c3 };
man_str = new(cs);
return true;
}
For 0x2674 I would expect "IST", but get "IųT".
Any Ideas?
Just use easier to read bit-masking:
char c1 = (char)(((man_hex & 0b111110000000000) >>10) + 64);
char c2 = (char)(((man_hex & 0b000001111100000) >> 5) + 64);
char c3 = (char)(((man_hex & 0b000000000011111) >> 0) + 64);
char[] cs = { c1, c2, c3 };
The particular error in your code is in computing c2 as you are not masking higher bits (15-10). If you want to keep math instead bitwise:
char c2 = (char)((man_hex % 1024 / 32) + 64);
I am not familiar with PHP code. I want to convert PHP code implemented UUID V1 to C#. I have tried many ways but it fails. Which part of code is wrong?
This C# code produces wrong GUID fa570fa10-3b235-472b-500-1ebc212c87e0 with node parameter of 138417599493834080 (the result can be vary depends on unix date time). When I change method Hex2Dec as written here it produces 393031383131343830-3234313135-3138323139-313238-1ebc212c87e0. I have no more idea about the wrong code. Please help me to solve it.
public static function v1($node)
{
// nano second time (only micro second precision) since start of UTC
$time = microtime(true) * 10000000 + 0x01b21dd213814000;
$time = pack("H*", sprintf('%016x', $time));
$sequence = random_bytes(2);
$sequence[0] = chr(ord($sequence[0]) & 0x3f | 0x80); // variant bits 10x
$time[0] = chr(ord($time[0]) & 0x0f | 0x10); // version bits 0001
if (!empty($node)) {
// non hex string identifier
if (is_string($node) && preg_match('/[^a-f0-9]/is', $node)) {
// base node off md5 hash for sequence
$node = md5($node);
// set multicast bit not IEEE 802 MAC
$node = (hexdec(substr($node, 0, 2)) | 1) . substr($node, 2, 10);
}
if (is_numeric($node))
$node = sprintf('%012x', $node);
$len = strlen($node);
if ($len > 12)
$node = substr($node, 0, 12);
else if ($len < 12)
$node .= str_repeat('0', 12 - $len);
} else {
// base node off random sequence
$node = random_bytes(6);
// set multicast bit not IEEE 802 MAC
$node[0] = chr(ord($node[0]) | 1);
$node = bin2hex($node);
}
return bin2hex($time[4] . $time[5] . $time[6] . $time[7]) // time low
. '-' . bin2hex($time[2] . $time[3]) // time med
. '-' . bin2hex($time[0] . $time[1]) // time hi
. '-' . bin2hex($sequence) // seq
. '-' . $node; // node
}
This is the C# part
public static string MD5(this string input)
{
// Use input string to calculate MD5 hash
using (System.Security.Cryptography.MD5 crypto = System.Security.Cryptography.MD5.Create())
{
byte[] hashBytes = crypto.ComputeHash(Encoding.ASCII.GetBytes(input));
StringBuilder sb = new StringBuilder();
for (int i = 0; i < hashBytes.Length; i++)
sb.Append(hashBytes[i].ToString("x2"));
return sb.ToString();
}
}
public static string GenerateGuidV1(string node)
{
var xtime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() * 10000000 + 0x01b21dd213814000;
var time = Pack(xtime.ToString("x"));
var sequence = new byte[2];
sequence[0] = (byte)((char)sequence[0] & 0x3f | 0x80); // variant bits 10x
time[0] = (byte)((char)time[0] & 0x0f | 0x10); // version bits 0001
if (!string.IsNullOrWhiteSpace(node))
{
// non hex string identifier
if (!IsNumeric(node) && Regex.IsMatch(node, "/[^a-f0-9]/is", RegexOptions.IgnoreCase))
//if (preg_match('/[^a-f0-9]/is', $node))
{
// base node off md5 hash for sequence
//$node = md5($node);
node = node.MD5();
// set multicast bit not IEEE 802 MAC
//$node = (hexdec(substr($node, 0, 2)) | 1) . substr($node, 2, 10);
node = (int.Parse(node.Substring(0, 2), NumberStyles.HexNumber) | 1) + node.Substring(2, 10);
}
if (IsNumeric(node))
node = Convert.ToInt64(node).ToString("x"); //sprintf('%012x', $node);
var len = node.Length;
if (len > 12)
node = node.Substring(0, 12); //substr($node, 0, 12);
else if (len < 12)
node += string.Concat(Enumerable.Repeat("0", 12 - len));//str_repeat('0', 12 - $len);
}
else
{
// base node off random sequence
var seqNode = new byte[6];//$node = random_bytes(6);
// set multicast bit not IEEE 802 MAC
seqNode[0] = (byte)((char)node[0] | 1);//$node[0] = chr(ord($node[0]) | 1);
node = Convert.ToInt16(seqNode[0].ToString(), 2).ToString("x");//bin2hex($node);
}
return Bin2Hex(time[4].ToString() + time[5].ToString() + time[6].ToString() + time[7].ToString()) // time low
+ '-'+ Bin2Hex(time[2].ToString() + time[3].ToString()) // time med
+ '-'+ Bin2Hex(time[0].ToString() + time[1].ToString()) // time hi
+ '-'+ Bin2Hex(sequence[0].ToString() + sequence[1].ToString()) // seq
+ '-'+ node; // node
}
private static string Bin2Hex(string value)
{
return Convert.ToInt64(value).ToString("x");
//byte[] bytes = Encoding.GetEncoding(1252).GetBytes(value);
//string hexString = "";
//for (int ii = 0; ii < bytes.Length; ii++)
//{
// hexString += bytes[ii].ToString("x2");
//}
//return hexString;
}
private static byte[] Pack(string hex)
{
hex = hex.Replace("-", "");
byte[] raw = new byte[hex.Length / 2];
for (int i = 0; i < raw.Length; i++)
{
raw[i] = Convert.ToByte(hex.Substring(i * 2, 2), 16);
}
return raw;
}
private static bool IsNumeric(string value) => value.All(char.IsNumber);
I have an aspx application where I make a hash to send it to the bank so that a monetary transaction be made. I'm experiencing a very strange problem: when I run the application locally in the development server of visual studio 2010, the hash gets computed correctly, but in the published application in the production server, the hash no longer gets computed correctly, it doesn't throw any error, but the resulting hash is not correct (saying that it's incorrect doesn't mean that its not a hash, but it's not the expected hash)
The function that returns the hash is as follows:
string codificar = afiliacion.ToString().Trim() +
tienda.ToString().Trim() +
terminal.Trim() +
total_orden.ToString().Trim() +
moneda.ToString().Trim() +
numOrd.ToString().Trim();
SHA1 cod = new SHA1Managed();
UTF8Encoding codificado = new UTF8Encoding();
byte[] stream = codificado.GetBytes(codificar);
StringBuilder sb = new StringBuilder();
var hash = cod.ComputeHash(stream);
foreach (var b in hash)
{
sb.Append(b.ToString("X2"));
}
foreach (var laorden in categoriaBuscados)
{
TNumsOrdenAFoliosMovimiento registro = new TNumsOrdenAFoliosMovimiento();
registro.numOrden = laorden.NumOrden;
registro.Digest = sb.ToString().ToLower();
try
{
modelo.TNumsOrdenAFoliosMovimiento.AddObject(registro);
modelo.SaveChanges();
}
catch (Exception el)
{
Response.Write(el.Message);
}
Any suggestion will be welcome greatly, because I have no idea why this may be happening. I mean, it's theoretically impossible that the same code works differently from the local version to the published version, isn't it?
Since the strings are not displayed to users and used only to generate hashes, update the ToString calls to ToString(CultureInfo.InvariantCulture) -- that will ensure the are stringified using the same rules locally and on the production server.
string codificar = afiliacion.ToString(CultureInfo.InvariantCulture).Trim() +
tienda.ToString(CultureInfo.InvariantCulture).Trim() +
terminal.Trim() +
total_orden.ToString(CultureInfo.InvariantCulture).Trim() +
moneda.ToString(CultureInfo.InvariantCulture).Trim() +
numOrd.ToString(CultureInfo.InvariantCulture).Trim();
It seemed like the problem was with the dll mscorlib that was in the production server, which version was different from the one I use in development. So eventually I came up with another solution and instead of using the UTF8Encoding class and get the bytes from the string I built the bytes using javascript then passed them to the code behind. Now the two hashes are equal and there are no more errors. Thank you all for your comments. I still do not know how to close a question here.
The javascript code I used to build the byte array is as follows:
<script type="text/javascript">
window.onload = function () {
var referencia = document.getElementById("referencia");
console.log(referencia.value);
referencia.value = getBytes(utf8_encode(referencia.value));
}
function getBytes(str) {
var bytes = [];
var charCode;
for (var i = 0; i < str.length; ++i) {
charCode = str.charCodeAt(i);
bytes.push((charCode & 0xFF00) >> 8);
bytes.push(charCode & 0xFF);
}
return bytes;
}
function utf8_encode(argString) {
if (argString === null || typeof argString === 'undefined') {
return '';
}
var string = (argString + ''); // .replace(/\r\n/g, "\n").replace(/\r/g, "\n");
var utftext = '',
start, end, stringl = 0;
start = end = 0;
stringl = string.length;
for (var n = 0; n < stringl; n++) {
var c1 = string.charCodeAt(n);
var enc = null;
if (c1 < 128) {
end++;
} else if (c1 > 127 && c1 < 2048) {
enc = String.fromCharCode(
(c1 >> 6) | 192, (c1 & 63) | 128
);
} else if ((c1 & 0xF800) != 0xD800) {
enc = String.fromCharCode(
(c1 >> 12) | 224, ((c1 >> 6) & 63) | 128, (c1 & 63) | 128
);
} else { // surrogate pairs
if ((c1 & 0xFC00) != 0xD800) {
throw new RangeError('Unmatched trail surrogate at ' + n);
}
var c2 = string.charCodeAt(++n);
if ((c2 & 0xFC00) != 0xDC00) {
throw new RangeError('Unmatched lead surrogate at ' + (n - 1));
}
c1 = ((c1 & 0x3FF) << 10) + (c2 & 0x3FF) + 0x10000;
enc = String.fromCharCode(
(c1 >> 18) | 240, ((c1 >> 12) & 63) | 128, ((c1 >> 6) & 63) | 128, (c1 & 63) | 128
);
}
if (enc !== null) {
if (end > start) {
utftext += string.slice(start, end);
}
utftext += enc;
start = end = n + 1;
}
}
if (end > start) {
utftext += string.slice(start, stringl);
}
return utftext;
}
</script>
I'm trying to compare two strings(Tx & Rx data) and find the quantity of unequal chars.
With the help of the following code, I managed to get the quantity,
string TxData = "00001111";
string RxData = "00000000";
int distorted = 0;
for (int i = 0; i < TxData.Length; i++)
{
if (TxData[i] != RxData[i])
distorted++;
}
Console.Write("Distorted Bits (qty) : {0}", distorted);
Result:
Distorted Bits (qty) : 4
But I'm very curious to know if there's any better way to do this task?
Thanks for your time...:)
If they're always the same length:
int distorted = TxData.Zip(RxData, (a,b) => a == b ? 0 : 1).Sum();
I like okrumnows answer by its simplisity, but assuming that you really already have bytes (or int) and don't need to convert them to string in the first place, you would probably be better of doing something like:
int myMethod(byte byte1, byte byte2)
{
//byte1 = Convert.ToByte("10010101",2);
//byte2 = Convert.ToByte("10011101",2);
byte xorvalue = (byte)( byte1 ^ byte2);
return NumberOfSetBits(xorvalue);
}
private static int NumberOfSetBits(uint i)
{
i = i - ((i >> 1) & 0x55555555);
i = (i & 0x33333333) + ((i >> 2) & 0x33333333);
return (((i + (i >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24;
}
This will be much faster.
I have a List<bool> which I want to convert to a byte[]. How do i do this?
list.toArray() creates a bool[].
Here's two approaches, depending on whether you want to pack the bits into bytes, or have as many bytes as original bits:
bool[] bools = { true, false, true, false, false, true, false, true,
true };
// basic - same count
byte[] arr1 = Array.ConvertAll(bools, b => b ? (byte)1 : (byte)0);
// pack (in this case, using the first bool as the lsb - if you want
// the first bool as the msb, reverse things ;-p)
int bytes = bools.Length / 8;
if ((bools.Length % 8) != 0) bytes++;
byte[] arr2 = new byte[bytes];
int bitIndex = 0, byteIndex = 0;
for (int i = 0; i < bools.Length; i++)
{
if (bools[i])
{
arr2[byteIndex] |= (byte)(((byte)1) << bitIndex);
}
bitIndex++;
if (bitIndex == 8)
{
bitIndex = 0;
byteIndex++;
}
}
Marc's answer is good already, but...
Assuming you are the kind of person that is comfortable doing bit-twiddling, or just want to write less code and squeeze out some more performance, then this here code is for you good sir / madame:
byte[] PackBoolsInByteArray(bool[] bools)
{
int len = bools.Length;
int bytes = len >> 3;
if ((len & 0x07) != 0) ++bytes;
byte[] arr2 = new byte[bytes];
for (int i = 0; i < bools.Length; i++)
{
if (bools[i])
arr2[i >> 3] |= (byte)(1 << (i & 0x07));
}
}
It does the exact same thing as Marc's code, it's just more succinct.
Of course if we really want to go all out we could unroll it too...
...and while we are at it lets throw in a curve ball on the return type!
IEnumerable<byte> PackBoolsInByteEnumerable(bool[] bools)
{
int len = bools.Length;
int rem = len & 0x07; // hint: rem = len % 8.
/*
byte[] byteArr = rem == 0 // length is a multiple of 8? (no remainder?)
? new byte[len >> 3] // -yes-
: new byte[(len >> 3)+ 1]; // -no-
*/
const byte BZ = 0,
B0 = 1 << 0, B1 = 1 << 1, B2 = 1 << 2, B3 = 1 << 3,
B4 = 1 << 4, B5 = 1 << 5, B6 = 1 << 6, B7 = 1 << 7;
byte b;
int i = 0;
for (int mul = len & ~0x07; i < mul; i += 8) // hint: len = mul + rem.
{
b = bools[i] ? B0 : BZ;
if (bools[i + 1]) b |= B1;
if (bools[i + 2]) b |= B2;
if (bools[i + 3]) b |= B3;
if (bools[i + 4]) b |= B4;
if (bools[i + 5]) b |= B5;
if (bools[i + 6]) b |= B6;
if (bools[i + 7]) b |= B7;
//byteArr[i >> 3] = b;
yield return b;
}
if (rem != 0) // take care of the remainder...
{
b = bools[i] ? B0 : BZ; // (there is at least one more bool.)
switch (rem) // rem is [1:7] (fall-through switch!)
{
case 7:
if (bools[i + 6]) b |= B6;
goto case 6;
case 6:
if (bools[i + 5]) b |= B5;
goto case 5;
case 5:
if (bools[i + 4]) b |= B4;
goto case 4;
case 4:
if (bools[i + 3]) b |= B3;
goto case 3;
case 3:
if (bools[i + 2]) b |= B2;
goto case 2;
case 2:
if (bools[i + 1]) b |= B1;
break;
// case 1 is the statement above the switch!
}
//byteArr[i >> 3] = b; // write the last byte to the array.
yield return b; // yield the last byte.
}
//return byteArr;
}
Tip: As you can see I included the code for returning a byte[] as comments. Simply comment out the two yield statements instead if that is what you want/need.
Twiddling Hints:
Shifting x >> 3 is a cheaper x / 8.
Masking x & 0x07 is a cheaper x % 8.
Masking x & ~0x07 is a cheaper x - x % 8.
Edit:
Here is some example documentation:
/// <summary>
/// Bit-packs an array of booleans into bytes, one bit per boolean.
/// </summary><remarks>
/// Booleans are bit-packed into bytes, in order, from least significant
/// bit to most significant bit of each byte.<br/>
/// If the length of the input array isn't a multiple of eight, then one
/// or more of the most significant bits in the last byte returned will
/// be unused. Unused bits are zero / unset.
/// </remarks>
/// <param name="bools">An array of booleans to pack into bytes.</param>
/// <returns>
/// An IEnumerable<byte> of bytes each containing (up to) eight
/// bit-packed booleans.
/// </returns>
You can use LINQ. This won't be efficient, but will be simple. I'm assuming that you want one byte per bool.
bool[] a = new bool[] { true, false, true, true, false, true };
byte[] b = (from x in a select x ? (byte)0x1 : (byte)0x0).ToArray();
Or the IEnumerable approach to AnorZaken's answer:
static IEnumerable<byte> PackBools(IEnumerable<bool> bools)
{
int bitIndex = 0;
byte currentByte = 0;
foreach (bool val in bools) {
if (val)
currentByte |= (byte)(1 << bitIndex);
if (++bitIndex == 8) {
yield return currentByte;
bitIndex = 0;
currentByte = 0;
}
}
if (bitIndex != 8) {
yield return currentByte;
}
}
And the according unpacking where paddingEnd means the amount of bits to discard from the last byte to unpack:
static IEnumerable<bool> UnpackBools(IEnumerable<byte> bytes, int paddingEnd = 0)
{
using (var enumerator = bytes.GetEnumerator()) {
bool last = !enumerator.MoveNext();
while (!last) {
byte current = enumerator.Current;
last = !enumerator.MoveNext();
for (int i = 0; i < 8 - (last ? paddingEnd : 0); i++) {
yield return (current & (1 << i)) != 0;
}
}
}
}
If you have any control over the type of list, try to make it a List, which will then produce the byte[] on ToArray(). If you have an ArrayList, you can use:
(byte[])list.ToArray(typeof(byte));
To get the List, you could create one with your unspecified list iterator as an input to the constructor, and then produce the ToArray()? Or copy each item, casting to a new byte from bool?
Some info on what type of list it is might help.
Have a look at the BitConverter class. Depending on the exact nature of your requirement, it may solve your problem quite neatly.
Another LINQ approach, less effective than #hfcs101's but would easily work for other value types as well:
var a = new [] { true, false, true, true, false, true };
byte[] b = a.Select(BitConverter.GetBytes).SelectMany(x => x).ToArray();