|
After reviewing your code and reading through the existing comments, it’s clear you've received some valuable suggestions for improvement. However, I’d like to offer a different perspective. If your goal is to maximize speed for your audio-related conversion, I have an alternative method to suggest, along with some benchmarks comparing it to your current approach.
TL;DR the results:
Quote: BenchmarkDotNet v0.14.0, Windows 10 (10.0.19045.4651/22H2/2022Update)
11th Gen Intel Core i9-11950H 2.60GHz, 1 CPU, 16 logical and 8 physical cores
.NET SDK 9.0.100-preview.3.24204.13
[Host] : .NET 8.0.6 (8.0.624.26715), X64 RyuJIT AVX-512F+CD+BW+DQ+VL+VBMI [AttachedDebugger]
DefaultJob : .NET 8.0.6 (8.0.624.26715), X64 RyuJIT AVX-512F+CD+BW+DQ+VL+VBMI
| Method | ArraySize | Mean | Error | StdDev | Ratio | RatioSD |
|----------------- |---------- |--------------- -------------- -------------- ------ --------
| CharlesHenington | 0 | 2.867 ns | 0.0456 ns | 0.0426 ns | 1.00 | 0.02 |
| GeorgeSwan | 0 | 2.652 ns | 0.0568 ns | 0.0504 ns | 0.93 | 0.02 |
| BufferBlockCopy | 0 | 8.933 ns | 0.1486 ns | 0.1390 ns | 3.12 | 0.06 |
| Hawkynt | 0 | 3.266 ns | 0.0796 ns | 0.0745 ns | 1.14 | 0.03 |
| | | | | | | |
| CharlesHenington | 1 | 3.199 ns | 0.0697 ns | 0.0618 ns | 1.00 | 0.03 |
| GeorgeSwan | 1 | 3.586 ns | 0.0648 ns | 0.0541 ns | 1.12 | 0.03 |
| BufferBlockCopy | 1 | 8.980 ns | 0.1237 ns | 0.1157 ns | 2.81 | 0.06 |
| Hawkynt | 1 | 3.507 ns | 0.0621 ns | 0.0485 ns | 1.10 | 0.03 |
| | | | | | | |
| CharlesHenington | 2 | 3.825 ns | 0.0834 ns | 0.0780 ns | 1.00 | 0.03 |
| GeorgeSwan | 2 | 4.922 ns | 0.0659 ns | 0.0617 ns | 1.29 | 0.03 |
| BufferBlockCopy | 2 | 10.489 ns | 0.0780 ns | 0.0691 ns | 2.74 | 0.06 |
| Hawkynt | 2 | 4.224 ns | 0.0623 ns | 0.0583 ns | 1.10 | 0.03 |
| | | | | | | |
| CharlesHenington | 3 | 3.784 ns | 0.0722 ns | 0.0640 ns | 1.00 | 0.02 |
| GeorgeSwan | 3 | 5.972 ns | 0.1318 ns | 0.1233 ns | 1.58 | 0.04 |
| BufferBlockCopy | 3 | 9.868 ns | 0.1085 ns | 0.1015 ns | 2.61 | 0.05 |
| Hawkynt | 3 | 4.149 ns | 0.0634 ns | 0.0529 ns | 1.10 | 0.02 |
| | | | | | | |
| CharlesHenington | 4 | 4.031 ns | 0.0742 ns | 0.0658 ns | 1.00 | 0.02 |
| GeorgeSwan | 4 | 7.178 ns | 0.0815 ns | 0.0762 ns | 1.78 | 0.03 |
| BufferBlockCopy | 4 | 9.472 ns | 0.1750 ns | 0.1552 ns | 2.35 | 0.05 |
| Hawkynt | 4 | 4.297 ns | 0.1083 ns | 0.1064 ns | 1.07 | 0.03 |
| | | | | | | |
| CharlesHenington | 5 | 4.141 ns | 0.0904 ns | 0.0846 ns | 1.00 | 0.03 |
| GeorgeSwan | 5 | 8.544 ns | 0.1891 ns | 0.2322 ns | 2.06 | 0.07 |
| BufferBlockCopy | 5 | 9.545 ns | 0.1052 ns | 0.1638 ns | 2.31 | 0.06 |
| Hawkynt | 5 | 4.348 ns | 0.0959 ns | 0.1027 ns | 1.05 | 0.03 |
| | | | | | | |
| CharlesHenington | 6 | 4.524 ns | 0.0775 ns | 0.0605 ns | 1.00 | 0.02 |
| GeorgeSwan | 6 | 9.034 ns | 0.1142 ns | 0.1068 ns | 2.00 | 0.04 |
| BufferBlockCopy | 6 | 9.621 ns | 0.0818 ns | 0.0683 ns | 2.13 | 0.03 |
| Hawkynt | 6 | 4.387 ns | 0.0720 ns | 0.0673 ns | 0.97 | 0.02 |
| | | | | | | |
| CharlesHenington | 7 | 4.570 ns | 0.0924 ns | 0.0819 ns | 1.00 | 0.02 |
| GeorgeSwan | 7 | 10.324 ns | 0.1752 ns | 0.1463 ns | 2.26 | 0.05 |
| BufferBlockCopy | 7 | 9.814 ns | 0.1516 ns | 0.1266 ns | 2.15 | 0.05 |
| Hawkynt | 7 | 4.364 ns | 0.1031 ns | 0.1058 ns | 0.96 | 0.03 |
| | | | | | | |
| CharlesHenington | 8 | 5.040 ns | 0.1238 ns | 0.2200 ns | 1.00 | 0.06 |
| GeorgeSwan | 8 | 11.637 ns | 0.2525 ns | 0.2362 ns | 2.31 | 0.11 |
| BufferBlockCopy | 8 | 10.043 ns | 0.2073 ns | 0.2304 ns | 2.00 | 0.09 |
| Hawkynt | 8 | 4.239 ns | 0.0764 ns | 0.0678 ns | 0.84 | 0.04 |
| | | | | | | |
| CharlesHenington | 10 | 5.788 ns | 0.1234 ns | 0.1094 ns | 1.00 | 0.03 |
| GeorgeSwan | 10 | 13.647 ns | 0.1929 ns | 0.1710 ns | 2.36 | 0.05 |
| BufferBlockCopy | 10 | 9.911 ns | 0.1507 ns | 0.1409 ns | 1.71 | 0.04 |
| Hawkynt | 10 | 5.714 ns | 0.1106 ns | 0.1035 ns | 0.99 | 0.02 |
| | | | | | | |
| CharlesHenington | 12 | 6.068 ns | 0.1095 ns | 0.0971 ns | 1.00 | 0.02 |
| GeorgeSwan | 12 | 15.491 ns | 0.1899 ns | 0.1776 ns | 2.55 | 0.05 |
| BufferBlockCopy | 12 | 9.640 ns | 0.2152 ns | 0.2210 ns | 1.59 | 0.04 |
| Hawkynt | 12 | 5.674 ns | 0.0974 ns | 0.0911 ns | 0.94 | 0.02 |
| | | | | | | |
| CharlesHenington | 14 | 6.552 ns | 0.0894 ns | 0.0793 ns | 1.00 | 0.02 |
| GeorgeSwan | 14 | 17.905 ns | 0.3773 ns | 0.3529 ns | 2.73 | 0.06 |
| BufferBlockCopy | 14 | 9.831 ns | 0.1092 ns | 0.0912 ns | 1.50 | 0.02 |
| Hawkynt | 14 | 5.690 ns | 0.0979 ns | 0.0915 ns | 0.87 | 0.02 |
| | | | | | | |
| CharlesHenington | 16 | 7.161 ns | 0.1508 ns | 0.1411 ns | 1.00 | 0.03 |
| GeorgeSwan | 16 | 20.149 ns | 0.1629 ns | 0.1272 ns | 2.81 | 0.06 |
| BufferBlockCopy | 16 | 9.841 ns | 0.1662 ns | 0.1554 ns | 1.37 | 0.03 |
| Hawkynt | 16 | 6.122 ns | 0.1000 ns | 0.0886 ns | 0.86 | 0.02 |
| | | | | | | |
| CharlesHenington | 100 | 32.404 ns | 0.5817 ns | 0.5441 ns | 1.00 | 0.02 |
| GeorgeSwan | 100 | 119.744 ns | 1.0700 ns | 0.9485 ns | 3.70 | 0.07 |
| BufferBlockCopy | 100 | 13.340 ns | 0.1519 ns | 0.1346 ns | 0.41 | 0.01 |
| Hawkynt | 100 | 9.394 ns | 0.1396 ns | 0.1306 ns | 0.29 | 0.01 |
| | | | | | | |
| CharlesHenington | 3200 | 647.414 ns | 7.2307 ns | 6.7636 ns | 1.00 | 0.01 |
| GeorgeSwan | 3200 | 3,453.941 ns | 27.4155 ns | 25.6445 ns | 5.34 | 0.07 |
| BufferBlockCopy | 3200 | 132.376 ns | 0.9534 ns | 0.8918 ns | 0.20 | 0.00 |
| Hawkynt | 3200 | 119.747 ns | 2.3510 ns | 3.2958 ns | 0.18 | 0.01 |
| | | | | | | |
| CharlesHenington | 11025 | 2,172.936 ns | 25.2469 ns | 22.3807 ns | 1.00 | 0.01 |
| GeorgeSwan | 11025 | 11,824.237 ns | 85.0400 ns | 75.3857 ns | 5.44 | 0.06 |
| BufferBlockCopy | 11025 | 385.451 ns | 7.5880 ns | 6.7266 ns | 0.18 | 0.00 |
| Hawkynt | 11025 | 396.096 ns | 4.3619 ns | 4.4793 ns | 0.18 | 0.00 |
| | | | | | | |
| CharlesHenington | 22050 | 4,414.342 ns | 42.7922 ns | 40.0278 ns | 1.00 | 0.01 |
| GeorgeSwan | 22050 | 23,455.660 ns | 133.7755 ns | 118.5885 ns | 5.31 | 0.05 |
| BufferBlockCopy | 22050 | 805.459 ns | 14.1072 ns | 12.5056 ns | 0.18 | 0.00 |
| Hawkynt | 22050 | 836.101 ns | 16.6413 ns | 30.0077 ns | 0.19 | 0.01 |
| | | | | | | |
| CharlesHenington | 44100 | 8,741.491 ns | 125.3789 ns | 104.6971 ns | 1.00 | 0.02 |
| GeorgeSwan | 44100 | 45,600.153 ns | 383.3263 ns | 358.5637 ns | 5.22 | 0.07 |
| BufferBlockCopy | 44100 | 2,104.648 ns | 38.5773 ns | 36.0852 ns | 0.24 | 0.00 |
| Hawkynt | 44100 | 2,152.238 ns | 18.7546 ns | 15.6609 ns | 0.25 | 0.00 |
| | | | | | | |
| CharlesHenington | 48000 | 9,453.950 ns | 91.0283 ns | 80.6942 ns | 1.00 | 0.01 |
| GeorgeSwan | 48000 | 49,454.773 ns | 342.8557 ns | 320.7074 ns | 5.23 | 0.05 |
| BufferBlockCopy | 48000 | 2,340.245 ns | 42.8133 ns | 40.0476 ns | 0.25 | 0.00 |
| Hawkynt | 48000 | 2,322.503 ns | 27.2077 ns | 25.4501 ns | 0.25 | 0.00 |
| | | | | | | |
| CharlesHenington | 96000 | 43,552.606 ns | 300.8701 ns | 281.4341 ns | 1.00 | 0.01 |
| GeorgeSwan | 96000 | 128,840.415 ns | 1,081.0900 ns | 1,011.2522 ns | 2.96 | 0.03 |
| BufferBlockCopy | 96000 | 34,951.609 ns | 523.7410 ns | 489.9076 ns | 0.80 | 0.01 |
| Hawkynt | 96000 | 33,729.029 ns | 583.4537 ns | 545.7630 ns | 0.77 | 0.01 |
| | | | | | | |
| CharlesHenington | 192000 | 88,196.524 ns | 1,064.7532 ns | 995.9708 ns | 1.00 | 0.02 |
| GeorgeSwan | 192000 | 260,512.458 ns | 2,030.4894 ns | 1,899.3210 ns | 2.95 | 0.04 |
| BufferBlockCopy | 192000 | 69,638.689 ns | 1,202.5732 ns | 1,124.8878 ns | 0.79 | 0.02 |
| Hawkynt | 192000 | 66,311.854 ns | 1,296.6680 ns | 1,212.9040 ns | 0.75 | 0.02 |
And here the test-code:
using System.Runtime.InteropServices;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
BenchmarkRunner.Run<BytesToShorts>();
public class BytesToShorts {
private byte[] data;
[Params(0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 100, 3200, 11025, 22050, 44100, 48000, 96000, 192000)]
public int ArraySize;
[GlobalSetup]
public void Setup() {
this.data = new byte[this.ArraySize];
new Random().NextBytes(this.data);
}
[Benchmark(Baseline = true)]
public void CharlesHenington() {
var result = Invoke(this.data);
static unsafe short[] Invoke(byte[] data) {
int length = data.Length / 2;
short[] array = new short[length];
fixed (byte* ptr = data) {
short* value = (short*)ptr;
for (int i = 0; i < length; i++, value++) {
array[i] = (short)*value;
}
}
return array;
}
}
[Benchmark]
public void GeorgeSwan() {
var result = Invoke(this.data);
static short[] Invoke(byte[] data) {
int arrayLength = (data.Length / 2) + data.Length % 2;
short[] array = new short[arrayLength];
for (int i = 0; i < data.Length; i++) {
int shiftN = (i % 2) * 8;
short shifted = (short)(data[i] << shiftN);
array[i / 2] = (short)(array[i / 2] | shifted);
}
return array;
}
}
[Benchmark]
public void BufferBlockCopy() {
var result = Invoke(this.data);
static short[] Invoke(byte[] data) {
var result = new short[data.Length / 2];
Buffer.BlockCopy(data, 0, result, 0, result.Length * 2);
return result;
}
}
[StructLayout(LayoutKind.Explicit, Size = 64)]
private struct Block64;
[Benchmark]
public void Hawkynt() {
var result = Invoke(this.data);
static unsafe short[] Invoke(byte[] data) {
int length = data.Length >> 1;
short[] result = new short[length];
fixed (byte* sourcePointer = data)
fixed (short* targetPointer = result) {
short* source = (short*)sourcePointer;
short* target = targetPointer;
for (;;)
switch (length) {
case 0:
return result;
case 1:
*target = *source;
return result;
case 2:
*(int*)target = *(int*)source;
return result;
case 3:
*(int*)target = *(int*)source;
target[2] = source[2];
return result;
case 4:
*(long*)target = *(long*)source;
return result;
default: {
while (length > 256) {
*(Block64*)target = *(Block64*)source;
((Block64*)target)[1] = ((Block64*)source)[1];
((Block64*)target)[2] = ((Block64*)source)[2];
((Block64*)target)[3] = ((Block64*)source)[3];
((Block64*)target)[4] = ((Block64*)source)[4];
((Block64*)target)[5] = ((Block64*)source)[5];
((Block64*)target)[6] = ((Block64*)source)[6];
((Block64*)target)[7] = ((Block64*)source)[7];
source += 256;
target += 256;
length -= 256;
}
while (length > 32) {
*(Block64*)target = *(Block64*)source;
source += 32;
target += 32;
length -= 32;
}
while (length >= 4) {
*(long*)target = *(long*)source;
source += 4;
target += 4;
length -= 4;
}
if (length == 0)
return result;
continue;
}
}
}
}
}
}
So what you could use is basically this method:
static unsafe short[] ToInt16Array(byte[] data) {
int length = data.Length >> 1;
short[] result = new short[length];
fixed (byte* sourcePointer = data)
fixed (short* targetPointer = result) {
short* source = (short*)sourcePointer;
short* target = targetPointer;
for (;;)
switch (length) {
case 0:
return result;
case 1:
*target = *source;
return result;
case 2:
*(int*)target = *(int*)source;
return result;
case 3:
*(int*)target = *(int*)source;
target[2] = source[2];
return result;
case 4:
*(long*)target = *(long*)source;
return result;
default: {
while (length > 256) {
*(Block64*)target = *(Block64*)source;
((Block64*)target)[1] = ((Block64*)source)[1];
((Block64*)target)[2] = ((Block64*)source)[2];
((Block64*)target)[3] = ((Block64*)source)[3];
((Block64*)target)[4] = ((Block64*)source)[4];
((Block64*)target)[5] = ((Block64*)source)[5];
((Block64*)target)[6] = ((Block64*)source)[6];
((Block64*)target)[7] = ((Block64*)source)[7];
source += 256;
target += 256;
length -= 256;
}
while (length > 32) {
*(Block64*)target = *(Block64*)source;
source += 32;
target += 32;
length -= 32;
}
while (length >= 4) {
*(long*)target = *(long*)source;
source += 4;
target += 4;
length -= 4;
}
if (length == 0)
return result;
continue;
}
}
}
}
Have a nice day
Try my C#-Extensions: https://github.com/Hawkynt/C--FrameworkExtensions
|
|
|
|
|
Absolutely incredible! Thank you for sharing! This is much faster than my unsafe example but Buffer.BlockCopy is still much faster.
|
|
|
|
|
Well it depends.
From the Benchmark results you can see, that Buffer.BlockCopy is damn slow for only a handful of elements and gets beaten by my routine for 96000 items and more.
You should test which method is best for YOUR item count on YOUR system.
|
|
|
|
|
Hacer un programa con un menú que pase de Kg a otra unidad de medida de masa, mostrar en pantalla un menú con las opciones posibles. Menú: Kg a libras Kg a onzas Kg a toneladas
|
|
|
|
|
While we are more than willing to help those that are stuck, that doesn't mean that we are here to do it all for you! We can't do all the work, you are either getting paid for this, or it's part of your grades and it wouldn't be at all fair for us to do it all for you.
So we need you to do the work, and we will help you when you get stuck. That doesn't mean we will give you a step by step solution you can hand in!
Start by explaining where you are at the moment, and what the next step in the process is. Then tell us what you have tried to get that next step working, and what happened when you did.
If you are having problems getting started at all, then this may help: How to Write Code to Solve a Problem, A Beginner's Guide[^]
Si bien estamos más que dispuestos a ayudar a quienes están estancados, eso no significa que estemos aquí para hacerlo todo por usted. No podemos hacer todo el trabajo, o le pagan por ello o es parte de sus calificaciones y no sería justo que lo hiciéramos todo por usted.
Por lo tanto, necesitamos que haga el trabajo y lo ayudaremos cuando se quede estancado. ¡Eso no significa que le daremos una solución paso a paso que pueda entregar!
Comience por explicar dónde se encuentra en este momento y cuál es el próximo paso en el proceso. Luego, cuéntenos qué ha intentado para que ese próximo paso funcione y qué sucedió cuando lo logró.
Si tienes problemas para empezar, esto puede ayudarte: Cómo escribir código para resolver un problema, una guía para principiantes[^]
"I have no idea what I did, but I'm taking full credit for it." - ThisOldTony
"Common sense is so rare these days, it should be classified as a super power" - Random T-shirt
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
Buffer.BlockCopy is the right method in this case.
It really outperforms any custom solution based on loops
PROS:
- Does not need unsafe context or cumbersome expressions (like pointers, bit shifting, type casts).
- Is specialized (copies blocks of memory, probably using dedicated system functions).
- Is a two-liner (you just need to allocate the new array and then call the method).
- Is flexible (can be used for any primitive-to-primitive conversion, not only bytes to shorts).
- Easy to debug.
- Exist since .NETFX 1.1.
CONS:
- Works only with primitive types (Byte, Int32, etc.)
You can try the following (very basic) fiddle: C# Online Compiler | .NET Fiddle.
It loops 1000000 on a byte array of 256 bytes.
The results are:
00:00:01.3003680 (1.300 seconds) for the bit-shift version by George Swan Convert byte[] to short[]
00:00:00.0572097 (0.057 seconds) for the Buffer.BlockCopy version.
The latter is 20 times faster than the first.
|
|
|
|
|
This is a reasonable advice. However, for several reasons, System.Array.ConvertAll would be better. It is less universal than BlockCopy and is much safer. Also, it should provide matching performance, at least I cannot see a reason why not.
Anyway, the advice suggested in the article has a negative value, it only suggests contamination of the code.
Thank you.
—SASergey A Kryukov
|
|
|
|
|
Buffer.BlockCopy gave good test results up to par with the unsafe code. Array.ConvertAll is insufficient and took much longer in my test results.
Test Output
Buffer.BlockCopy performed in 1.14596 seconds
Array.ConvertAll performed in 34.877525 seconds
In conclusion, both Buffer.BlockCopy and the unsafe example I provide outperform Array.ConvertAll.
modified 5-Aug-24 13:42pm.
|
|
|
|
|
Thank you. It looks a bit weird to me, but now it is a reasonable argument.
—SASergey A Kryukov
|
|
|
|
|
two reasons :
1. Array.ConvertAll is based on delegates, that involve additional CPU and memory usage, whereas Buffer.BlockCopy is close to old fashioned memcpy.
2. Array.ConvertAll is well suited for one-to-one conversions, but the goal here is to merge items; specifically to output 1 Int16 every 2 Byte inputs.
|
|
|
|
|
Your points are taken, thank you. I would say, then the final solution is a matter of most reasonable balance, suitable for a particular goal.
—SASergey A Kryukov
|
|
|
|
|
Thanks for the excellent post, Daniele, plus 5 from me. I tested the two methods using the definitive BenchmarkDotNet and got the following results.
| Method | Mean | Error | StdDev | Ratio |
|---------------- |----------:|----------:|----------:|------:|
| BlockCopy | 44.71 ns | 1.867 ns | 5.475 ns | 1.00 |
| BinaryShiftCopy | 532.11 ns | 12.625 ns | 36.425 ns | 12.10 |
I had to take the liberty of modifying your code slightly as it threw an exception when tested with an odd number of bytes. But there is no doubt that your suggestion is the best option and I shall edit my post so that it points to your solution.
short[] ToInt16ArrayB2(byte[] data)
{
int arrayLength = (data.Length / 2) + data.Length % 2;
var result = new short[arrayLength];
Buffer.BlockCopy(data, 0, result, 0, data.Length);
return result;
}
|
|
|
|
|
I'm glad I could help.
By the way, the fiddle was just an example for your convenience.
I knew about the exception with odd lengths, but it was out of performance topic.
Maybe, you can handle it also with Math.Floor or Math.Ceil, but your modulo approach is probably more readable and faster.
|
|
|
|
|
Sorry, this is pretty bad. First of all, you use unsafe without a reason. You can improve the code it by directly assigning each byte value to short , as the byte value set is assignment-compatible with the short value set.
Besides, you can use System.Array.ConvertAll<TInput,TOutput> . Please see the documentation page. In principle, there is nothing wrong with not using a standard library, but in your case you show a code sample that simply contaminate the product code with redundant lines. Such a contamination should be avoided by all means, because it makes the product code less and less manageable.
Thank you.
—SASergey A Kryukov
modified 5-Aug-24 0:24am.
|
|
|
|
|
I respect your opinion, I'm self taught and prefer to write code vs using prebuilt solutions as it helps me to better understand what's going on behind the scenes. I also prefer working with unsafe code as it tends to be faster on my ubuntu setup but I thank you for your insight.
|
|
|
|
|
Charles, I thought your tip was pretty good so +5 from me!
|
|
|
|
|
|
charles henington wrote: I'm self taught and prefer to write code vs using prebuilt solutions as it helps me to better understand… This is a quite respectful attitude. I also prefer doing everything by myself. But let's sort things out, different things. One thing is the research done for understanding. Another thing is the publication with practical recommendations. It can be misleading. You did not tell the readers that it was done for your understanding of what's going on. You did not recommend a library method as a practically most beneficial. The failure to explain all that and to give the best recommendation is what gives a negative value to your publications. Please, no offense, better take it as friendly advice.
charles henington wrote: unsafe code as it tends to be faster… Sorry, “tends” is by far not enough. If you recommend some technique based on performance, you could do the research and provide your benchmarks. But you hardly can find any miracles, as in nearly all simple cases a standard library method call is faster. If you try out and find otherwise, it would really be interesting. By the way, the standard library methods can internally use unsafe when it is necessary, but using them can help you to avoid unnecessary unsafe code in the assemblies using them.
Thank you for understanding.
—SASergey A Kryukov
|
|
|
|
|
Thanks for the interesting tip. Here is a version that uses a bit of bit shifting.
static short[] ToInt16ArrayB(byte[] data)
{
int arrayLength = (data.Length / 2)+data.Length%2;
short[] array = new short[arrayLength];
for(int i=0;i<data.Length;i++)
{
int shiftN = (i % 2) * 8;
short shifted= (short)(data[i]<<shiftN);
array[i / 2] = (short)(array[i / 2] | shifted);
}
return array;
}
Edit. A better solution has been posted here but I shall retain this method in the hope that it may be instructive.
modified 6-Aug-24 9:54am.
|
|
|
|
|
Very nice! Bit shift operators are one area I do need to learn, thanks for this.!
|
|
|
|
|
You need to learn not just this. And all the bitwise operators are so basic that you need to learn them before doing any work. I strongly suggest you have no unknown parts of the language and basic technologies before you try to publish anything at all. I already criticized your code and explained why it has no benefits and why such things should be avoided. Redundant code makes redundant publication.
Thank you for understanding.
—SA
Sergey A Kryukov
|
|
|
|
|
Your code sample is better because it does not use unsafe . But it is still redundant. For further detail, please see my other comment.
Thank you.
&dashSA;Sergey A Kryukov
modified 5-Aug-24 0:22am.
|
|
|
|
|
Thanks for your comment. Can you please post your solution?
|
|
|
|
|
My solution is already posted. This is one code line in my comment and a reference to the documentation page. Isn't it enough?
—SASergey A Kryukov
modified 5-Aug-24 0:23am.
|
|
|
|
|
Can you provide one using actual code, not just a reference to to a microsoft built-in, preferably using unsafe code if you could please.
modified 5-Aug-24 1:02am.
|
|
|
|
|