英文:
How to get constant hashcode (Uint32 or Int32) for a string but being outside of a range
问题
根据这篇文章,字符串的官方 "GetHashCode" 在每次执行时会随机生成,以防止黑客攻击。但我需要将哈希码持久化,所以希望它对于特定字符串始终保持相同。
在同一篇文章中,我看到了获取哈希码的方法,但我想知道是否有更好的解决方案,或者是否有一种可以直接获得哈希码的方法,而不受特定范围的限制(比如0 - 2000之外的Uint32)。
英文:
According to this article the official "GetHashCode" for a string is made randomly per execution to prevent Hacking. But I need to persist the hashcode so I want it to be always the same per specific string.
In the same article I saw a way to get an HashCode but I wonder if there is better solution and/or if there is a way to direcly get a Hash code outside of a specific range (like 0 - 2000)? Any Uint32 ouside of [0-2000].
答案1
得分: 0
**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]) &
<details>
<summary>英文:</summary>
**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);
}
}
**HOW TO USE?**
**A. For CRC32C**
uint result = Crc32C.Update(0, Encoding.ASCII.GetBytes("There is no God but Allah"));
MessageBox.Show(result.ToString("X")); // result: C16698CA
**B. For CRC32**
Change **poly** from
private const uint poly = 0x82f63b78u;
To
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
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论