gpt4 book ai didi

c# - 将 float 格式的 char[] 转换为 float

转载 作者:行者123 更新时间:2023-11-30 13:43:43 24 4
gpt4 key购买 nike

我有一个 char[] salary,它包含来自 string 的数据。我想将 char[] salary 转换为 float,但我尝试的方法似乎非常慢,即:

float ff = float.Parse(new string(salary));

根据 Visual Studio 的性能分析器,这占用了过多的处理时间:

enter image description here

所以我想知道是否有更快的方法来执行此操作,因为这里的性能很重要。char[] 的格式如下:

[ '1', '3', '2', ',', '2', '9']

并且基本上是一个类似 JSON 的 float ,转换为适合 char[] 的每个数字(和逗号)。

编辑:

我重新格式化了代码,看起来性能下降实际上是从 char[]string 的转换,而不是从 string 的解析 float

最佳答案

因为这个问题已经从“解析 float 的最快方法是什么?”改变了到“从 char[] 获取 string 的最快方法是什么?”,我用 BenchmarkDotNet 编写了一些基准测试比较各种方法。我的发现是,如果你已经有一个 char[],你不能比像你一样将它传递给 string(char[]) 构造函数更快已经在做。

你说你的输入文件是“读入一个byte[],然后是代表floatbyte[]部分> 被提取到 char[] 中。”由于您有构成 float 文本的 bytebyte[] 中隔离,也许您可​​以通过跳过中间 字符[]。假设你有等同于...

byte[] floatBytes = new byte[] { 0x31, 0x33, 0x32, 0x2C, 0x32, 0x39 }; // "132,29"

...你可以使用 Encoding.GetString() ...

string floatString = Encoding.ASCII.GetString(floatBytes);

...这几乎是传递 Encoding.GetChars() 结果的两倍到 string(char[]) 构造函数...

char[] floatChars = Encoding.ASCII.GetChars(floatBytes);
string floatString = new string(floatChars);

您会在我的结果中找到最后列出的那些基准...

BenchmarkDotNet=v0.11.0, OS=Windows 10.0.17134.165 (1803/April2018Update/Redstone4)
Intel Core i7 CPU 860 2.80GHz (Max: 2.79GHz) (Nehalem), 1 CPU, 8 logical and 4 physical cores
Frequency=2732436 Hz, Resolution=365.9738 ns, Timer=TSC
.NET Core SDK=2.1.202
[Host] : .NET Core 2.0.9 (CoreCLR 4.6.26614.01, CoreFX 4.6.26614.01), 64bit RyuJIT
Clr : .NET Framework 4.7.2 (CLR 4.0.30319.42000), 64bit RyuJIT-v4.7.3131.0
Core : .NET Core 2.0.9 (CoreCLR 4.6.26614.01, CoreFX 4.6.26614.01), 64bit RyuJIT


Method | Runtime | Categories | Mean | Scaled |
----------------------------------------------------- |-------- |----------------- |----------:|-------:|
String_Constructor_CharArray | Clr | char[] => string | 13.51 ns | 1.00 |
String_Concat | Clr | char[] => string | 192.87 ns | 14.27 |
StringBuilder_Local_AppendSingleChar_DefaultCapacity | Clr | char[] => string | 60.74 ns | 4.49 |
StringBuilder_Local_AppendSingleChar_ExactCapacity | Clr | char[] => string | 60.26 ns | 4.46 |
StringBuilder_Local_AppendAllChars_DefaultCapacity | Clr | char[] => string | 51.27 ns | 3.79 |
StringBuilder_Local_AppendAllChars_ExactCapacity | Clr | char[] => string | 49.51 ns | 3.66 |
StringBuilder_Field_AppendSingleChar | Clr | char[] => string | 51.14 ns | 3.78 |
StringBuilder_Field_AppendAllChars | Clr | char[] => string | 32.95 ns | 2.44 |
| | | | |
String_Constructor_CharPointer | Clr | void* => string | 29.28 ns | 1.00 |
String_Constructor_SBytePointer | Clr | void* => string | 89.21 ns | 3.05 |
UnsafeArrayCopy_String_Constructor | Clr | void* => string | 42.82 ns | 1.46 |
| | | | |
Encoding_GetString | Clr | byte[] => string | 37.33 ns | 1.00 |
Encoding_GetChars_String_Constructor | Clr | byte[] => string | 60.83 ns | 1.63 |
SafeArrayCopy_String_Constructor | Clr | byte[] => string | 27.55 ns | 0.74 |
| | | | |
String_Constructor_CharArray | Core | char[] => string | 13.27 ns | 1.00 |
String_Concat | Core | char[] => string | 172.17 ns | 12.97 |
StringBuilder_Local_AppendSingleChar_DefaultCapacity | Core | char[] => string | 58.68 ns | 4.42 |
StringBuilder_Local_AppendSingleChar_ExactCapacity | Core | char[] => string | 59.85 ns | 4.51 |
StringBuilder_Local_AppendAllChars_DefaultCapacity | Core | char[] => string | 40.62 ns | 3.06 |
StringBuilder_Local_AppendAllChars_ExactCapacity | Core | char[] => string | 43.67 ns | 3.29 |
StringBuilder_Field_AppendSingleChar | Core | char[] => string | 54.49 ns | 4.11 |
StringBuilder_Field_AppendAllChars | Core | char[] => string | 31.05 ns | 2.34 |
| | | | |
String_Constructor_CharPointer | Core | void* => string | 22.87 ns | 1.00 |
String_Constructor_SBytePointer | Core | void* => string | 83.11 ns | 3.63 |
UnsafeArrayCopy_String_Constructor | Core | void* => string | 35.30 ns | 1.54 |
| | | | |
Encoding_GetString | Core | byte[] => string | 36.19 ns | 1.00 |
Encoding_GetChars_String_Constructor | Core | byte[] => string | 58.99 ns | 1.63 |
SafeArrayCopy_String_Constructor | Core | byte[] => string | 27.81 ns | 0.77 |

...从运行此代码(需要 BenchmarkDotNet assembly 并使用 /unsafe 编译)...

using System;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using BenchmarkDotNet.Attributes;

namespace StackOverflow_51584129
{
[CategoriesColumn()]
[ClrJob()]
[CoreJob()]
[GroupBenchmarksBy(BenchmarkDotNet.Configs.BenchmarkLogicalGroupRule.ByCategory)]
public class StringCreationBenchmarks
{
private static readonly Encoding InputEncoding = Encoding.ASCII;

private const string InputString = "132,29";
private static readonly byte[] InputBytes = InputEncoding.GetBytes(InputString);
private static readonly char[] InputChars = InputString.ToCharArray();
private static readonly sbyte[] InputSBytes = InputBytes.Select(Convert.ToSByte).ToArray();

private GCHandle _inputBytesHandle;
private GCHandle _inputCharsHandle;
private GCHandle _inputSBytesHandle;

private StringBuilder _builder;

[Benchmark(Baseline = true)]
[BenchmarkCategory("char[] => string")]
public string String_Constructor_CharArray()
{
return new string(InputChars);
}

[Benchmark(Baseline = true)]
[BenchmarkCategory("void* => string")]
public unsafe string String_Constructor_CharPointer()
{
var pointer = (char*) _inputCharsHandle.AddrOfPinnedObject();

return new string(pointer);
}

[Benchmark()]
[BenchmarkCategory("void* => string")]
public unsafe string String_Constructor_SBytePointer()
{
var pointer = (sbyte*) _inputSBytesHandle.AddrOfPinnedObject();

return new string(pointer);
}

[Benchmark()]
[BenchmarkCategory("char[] => string")]
public string String_Concat()
{
return string.Concat(InputChars);
}

[Benchmark()]
[BenchmarkCategory("char[] => string")]
public string StringBuilder_Local_AppendSingleChar_DefaultCapacity()
{
var builder = new StringBuilder();

foreach (var c in InputChars)
builder.Append(c);

return builder.ToString();
}

[Benchmark()]
[BenchmarkCategory("char[] => string")]
public string StringBuilder_Local_AppendSingleChar_ExactCapacity()
{
var builder = new StringBuilder(InputChars.Length);

foreach (var c in InputChars)
builder.Append(c);

return builder.ToString();
}

[Benchmark()]
[BenchmarkCategory("char[] => string")]
public string StringBuilder_Local_AppendAllChars_DefaultCapacity()
{
var builder = new StringBuilder().Append(InputChars);

return builder.ToString();
}

[Benchmark()]
[BenchmarkCategory("char[] => string")]
public string StringBuilder_Local_AppendAllChars_ExactCapacity()
{
var builder = new StringBuilder(InputChars.Length).Append(InputChars);

return builder.ToString();
}

[Benchmark()]
[BenchmarkCategory("char[] => string")]
public string StringBuilder_Field_AppendSingleChar()
{
_builder.Clear();

foreach (var c in InputChars)
_builder.Append(c);

return _builder.ToString();
}

[Benchmark()]
[BenchmarkCategory("char[] => string")]
public string StringBuilder_Field_AppendAllChars()
{
return _builder.Clear().Append(InputChars).ToString();
}

[Benchmark(Baseline = true)]
[BenchmarkCategory("byte[] => string")]
public string Encoding_GetString()
{
return InputEncoding.GetString(InputBytes);
}

[Benchmark()]
[BenchmarkCategory("byte[] => string")]
public string Encoding_GetChars_String_Constructor()
{
var chars = InputEncoding.GetChars(InputBytes);

return new string(chars);
}

[Benchmark()]
[BenchmarkCategory("byte[] => string")]
public string SafeArrayCopy_String_Constructor()
{
var chars = new char[InputString.Length];

for (int i = 0; i < InputString.Length; i++)
chars[i] = Convert.ToChar(InputBytes[i]);

return new string(chars);
}

[Benchmark()]
[BenchmarkCategory("void* => string")]
public unsafe string UnsafeArrayCopy_String_Constructor()
{
fixed (char* chars = new char[InputString.Length])
{
var bytes = (byte*) _inputBytesHandle.AddrOfPinnedObject();

for (int i = 0; i < InputString.Length; i++)
chars[i] = Convert.ToChar(bytes[i]);

return new string(chars);
}
}

[GlobalSetup(Targets = new[] { nameof(StringBuilder_Field_AppendAllChars), nameof(StringBuilder_Field_AppendSingleChar) })]
public void SetupStringBuilderField()
{
_builder = new StringBuilder();
}

[GlobalSetup(Target = nameof(UnsafeArrayCopy_String_Constructor))]
public void SetupBytesHandle()
{
_inputBytesHandle = GCHandle.Alloc(InputBytes, GCHandleType.Pinned);
}

[GlobalCleanup(Target = nameof(UnsafeArrayCopy_String_Constructor))]
public void CleanupBytesHandle()
{
_inputBytesHandle.Free();
}

[GlobalSetup(Target = nameof(String_Constructor_CharPointer))]
public void SetupCharsHandle()
{
_inputCharsHandle = GCHandle.Alloc(InputChars, GCHandleType.Pinned);
}

[GlobalCleanup(Target = nameof(String_Constructor_CharPointer))]
public void CleanupCharsHandle()
{
_inputCharsHandle.Free();
}

[GlobalSetup(Target = nameof(String_Constructor_SBytePointer))]
public void SetupSByteHandle()
{
_inputSBytesHandle = GCHandle.Alloc(InputSBytes, GCHandleType.Pinned);
}

[GlobalCleanup(Target = nameof(String_Constructor_SBytePointer))]
public void CleanupSByteHandle()
{
_inputSBytesHandle.Free();
}

public static void Main(string[] args)
{
BenchmarkDotNet.Running.BenchmarkRunner.Run<StringCreationBenchmarks>();
}
}
}

关于c# - 将 float 格式的 char[] 转换为 float,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51584129/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com