Согласно этой статье официальный «GetHashCode» для строки создается случайным образом при каждом выполнении, чтобы предотвратить взлом. Но мне нужно сохранить хэш-код, поэтому я хочу, чтобы он всегда был одинаковым для каждой конкретной строки.
В той же статье я увидел способ получить хэш-код, но мне интересно, есть ли лучшее решение и/или есть ли способ напрямую получить хэш-код за пределами определенного диапазона (например, 0–2000)? Любой Uint32 кроме [0-2000].
Взгляните на stackoverflow.com/questions/1858947/…. Если вы хотите сделать это самостоятельно, это легко проверить, так как это стандартный алгоритм и есть онлайн-калькуляторы.
посмотрите код, который я разместил, который работал, для CRC32c poly = 0x82f63b78u и для CRC32 poly = 0xedb88320u
Посмотрите на часть //НЕ ДЛЯ КОНКРЕТНОЙ ОС// в Crc32C.cs. Не забудьте использовать poly = 0xedb88320u для CRC32.





Crc32C.ARM.cs
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Intrinsics.Arm;
namespace DiscountCard.Ext.Mod.CRC32
{
partial class Crc32C
{
public static class ImplARM
{
public static uint Update(uint crc, ReadOnlySpan<byte> input)
{
crc ^= uint.MaxValue;
while (input.Length >= 4)
{
crc = Crc32.ComputeCrc32C(crc, Unsafe.ReadUnaligned<uint>(ref MemoryMarshal.GetReference(input)));
input = input.Slice(sizeof(uint));
}
for (int i = 0; i < input.Length; i++)
{
crc = Crc32.ComputeCrc32C(crc, input[i]);
}
return crc ^ uint.MaxValue;
}
public static uint Update64(uint crc, ReadOnlySpan<byte> input)
{
crc ^= uint.MaxValue;
while (input.Length >= sizeof(ulong))
{
crc = Crc32.Arm64.ComputeCrc32C(crc, Unsafe.ReadUnaligned<ulong>(ref MemoryMarshal.GetReference(input)));
input = input.Slice(sizeof(ulong));
}
if (input.Length >= 4)
{
crc = Crc32.ComputeCrc32C(crc, Unsafe.ReadUnaligned<uint>(ref MemoryMarshal.GetReference(input)));
input = input.Slice(sizeof(uint));
}
for (int i = 0; i < input.Length; i++)
{
crc = Crc32.ComputeCrc32C(crc, input[i]);
}
return crc ^ uint.MaxValue;
}
}
}
}
Crc32C.X86.cs
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Intrinsics.X86;
namespace DiscountCard.Ext.Mod.CRC32
{
partial class Crc32C
{
public static class ImplX86
{
public static uint Update(uint crc, ReadOnlySpan<byte> input)
{
crc ^= uint.MaxValue;
while (input.Length >= sizeof(uint))
{
crc = Sse42.Crc32(crc, Unsafe.ReadUnaligned<uint>(ref MemoryMarshal.GetReference(input)));
input = input.Slice(sizeof(uint));
}
for (int i = 0; i < input.Length; i++)
{
crc = Sse42.Crc32(crc, (byte)input[i]);
}
return crc ^ uint.MaxValue;
}
public static uint Update64(uint crc, ReadOnlySpan<byte> input)
{
ulong crcl = crc ^ uint.MaxValue;
while (input.Length >= sizeof(ulong))
{
crcl = Sse42.X64.Crc32(crcl, Unsafe.ReadUnaligned<ulong>(ref MemoryMarshal.GetReference(input)));
input = input.Slice(sizeof(ulong));
}
crc = unchecked((uint)crcl);
if (input.Length >= 4)
{
crc = Sse42.Crc32(crc, Unsafe.ReadUnaligned<uint>(ref MemoryMarshal.GetReference(input)));
input = input.Slice(sizeof(uint));
}
for (int i = 0; i < input.Length; i++)
{
crc = Sse42.Crc32(crc, (byte)input[i]);
}
return crc ^ uint.MaxValue;
}
}
}
}
Crc32C.cs
#define X86_INTRINSICS
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
#if X86_INTRINSICS
using System.Runtime.Intrinsics.X86;
#endif
#if ARM_INTRINSICS
using System.Runtime.Intrinsics.Arm;
#endif
namespace DiscountCard.Ext.Mod.CRC32
{
public static unsafe partial class Crc32C
{
private static uint* table;
private const uint poly = 0x82f63b78u;
private static delegate*<uint, ReadOnlySpan<byte>, uint> ptr;
static Crc32C()
{
#if X86_INTRINSICS
if (Sse42.X64.IsSupported)
{
ptr = &ImplX86.Update64;
goto end_decision;
}
if (Sse42.IsSupported)
{
ptr = &ImplX86.Update;
goto end_decision;
}
#endif
#if ARM_INTRINSICS
if (Crc32.Arm64.IsSupported)
{
ptr = &ImplARM.Update64;
goto end_decision;
}
if (Crc32.IsSupported)
{
ptr = &ImplARM.Update;
goto end_decision;
}
#endif
// FOR NO SPECIFIC OS ///////////
InitializeTable();
if (BitConverter.IsLittleEndian)
{
ptr = &UpdateLittleEndianOptimized;
goto end_decision;
}
ptr = &UpdateNative;
// END OF FOR NO SPECIFIC OS ///
end_decision:;
}
static void InitializeTable()
{
table = (uint*)Marshal.AllocHGlobal(16 * 256 * 4);
for (uint i = 0; i < 256; i++)
{
uint res = i;
for (int t = 0; t < 16; t++)
{
for (int k = 0; k < 8; k++) res = (res & 1) == 1 ? poly ^ (res >> 1) : (res >> 1);
table[(t * 256) + i] = res;
}
}
}
static uint UpdateLittleEndianOptimized(uint crci, ReadOnlySpan<byte> input)
{
// Copyright (C) 2013 Mark Adler
ulong crc;
crc = crci ^ 0xffffffff;
while (input.Length >= sizeof(ulong))
{
crc ^= Unsafe.ReadUnaligned<ulong>(ref MemoryMarshal.GetReference(input));
crc = table[(7 * 256) + (crc & 0xff)] ^
table[(6 * 256) + ((crc >> 8) & 0xff)] ^
table[(5 * 256) + ((crc >> 16) & 0xff)] ^
table[(4 * 256) + ((crc >> 24) & 0xff)] ^
table[(3 * 256) + ((crc >> 32) & 0xff)] ^
table[(2 * 256) + ((crc >> 40) & 0xff)] ^
table[(1 * 256) + ((crc >> 48) & 0xff)] ^
table[(0 * 256) + (crc >> 56)];
input = input.Slice(sizeof(ulong));
}
for (int i = 0; i < input.Length; i++)
{
crc = table[(0 * 256) + ((crc ^ input[i]) & 0xff)] ^ (crc >> 8);
}
return (uint)crc ^ 0xffffffff;
}
static uint UpdateNative(uint crc, ReadOnlySpan<byte> input)
{
crc ^= uint.MaxValue;
for (int i = 0; i < input.Length; i++)
{
crc = table[(0 * 256) + ((crc ^ input[i]) & 0xff)] ^ (crc >> 8);
}
return crc ^ uint.MaxValue;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static uint Update(uint crc, ReadOnlySpan<byte> input) => ptr(crc, input);
}
}
КАК ИСПОЛЬЗОВАТЬ?
А. Для CRC32C
uint result = Crc32C.Update(0, Encoding.ASCII.GetBytes("There is no God but Allah"));
MessageBox.Show(result.ToString("X")); // result: C16698CA
Б. Для CRC32
Изменить поли из
private const uint poly = 0x82f63b78u;
К
private const uint poly = 0xedb88320u;
uint result = Crc32C.Update(0, Encoding.ASCII.GetBytes("There is no God but Allah"));
MessageBox.Show(result.ToString("X")); // result: 0xFABB17B6
В моем вопросе много ошибок. Я переспрошу более уместно. Чтобы поблагодарить вас за ваш ответ, я отмечу его как правильный. Спасибо.
Но я удалю его, потому что я не думаю, что он может помочь кому-нибудь в его фактической форме. У меня тоже ошибки в коде.
Я попытался удалить его, но получил большое предупреждение, поэтому я изменил его, чтобы он лучше соответствовал моим потребностям.
Документация, на которую вы ссылаетесь, не показывает метод
ComputeCrc32, толькоHash,TryHash,AppendиReset, и я не смог воспроизвести проблему при вызовеCrc32.Hash, т.е. он нашел пространство имен в директивеusingи смог чтобы использовать классCrc32из него.