I'm having an issue working from Arduino to Unity; essentially I'm building a payload struct in C++ (Arduino) and sending it to a PC using the following serial protocol:
1 byte - header
1 byte - payload size
X bytes - payload
1 byte - checksum (LRC)
The payload looks like so:
struct SamplePayload {
double A;
double B;
double C;
double D;
} payload;
when I sizeof(payload) I get 16 bytes, when I believe a double is an 8 byte data type; if I add another double the struct is 20 bytes and so on. Am I misunderstanding something? This is causing issues as this is then converted to a byte data stream and cast as a struct on receipt in C#, and I'm not sure what the equivalent datatype would be (casting as a double gives wrong values). The serial protocol in Unity also relies on the correct payload size to read out the stream.
It is probably a straightforward answer but I couldn't find it anywhere, many thanks!
If your application is not numerically sensitive, you could use the following approach:
Instead of using doubles within your struct (which aren't strictly standardized, as mentioned in the comments), you could use two int32_t, a and b for representing a significant and an exponent such that
a*2^b = original_double
So your struct will look something like this:
struct SamplePayload {
int32_t A_sig;
int32_t A_exp;
//B,C...
} payload;
Then on the receiving side, you will only have to multiply according to the formula above to get the original double.
C provides you with a neat function, frexp, to ease things up.
But since we store both a and b as integers, we need to modify the results a bit in order to get high precision.
Specifically, since a is guaranteed to be between 0.5 and 1, you need to multiply a by 2^30, and subtract 30 from b in order not to overflow.
Here's an example:
#include <stdio.h> /* printf */
#include <math.h> /* frexp */
#include <stdint.h>
int main ()
{
double param, result;
int32_t a,b;
param = +235.0123123;
result = frexp (param , &b);
a=(result*(1<<30)) /*2^30*/; b-=30;
printf ("%f = %d * 2^%d\n", param, a, b); //235.012312 = 985713081 * 2^-22
return 0;
}
Related
public static double[] ParseDoubleArray(MWArray array)
{
var vector2d = (array as MWNumericArray).ToArray() as double[,];
var vector1d = new double[vector2d.Length];
System.Buffer.BlockCopy(vector2d, 0, vector1d, 0, vector2d.Length * sizeof(double));
return vector1d;
}
this is my function for getting the double[] from MWArray
however why i do this:
prepImage.RawData = Array.ConvertAll(prepRawData, Convert.ToUInt16);
I sometimes get an exception because matlab is returning doubles too big for conversion.
has anyone came across this issue? i can crop the numbers but is there another solution?
UInt16, as its name implies, holds unsigned 16 bit integers (values from 0 to 65535). On the other hand, the double structure ranges from -1.79769313486232e308 to 1.79769313486232e308.
The issue here is that your Matlab code returns either a negative value, or a positive value greater than 65535. Matlab will also assign NaN to any uninitialized value which is also invalid for UInt16.
To fix your problem, either make sure that your Matlab code is really only returning values in the 0 to 65535 range or change the data structure on the C# side to something else than UInt16.
I am trying to explicity cast an int into a ushort but am getting the Cannot implicity convert type 'int' to 'ushort'
ushort quotient = ((12 * (ushort)(channel)) / 16);
I am using .Net Micro framework so BitConverter is unavailable. Why I am using ushort in the first place has to do with how my data is being sent over SPI. I can understand this particular error has been brought up before on this site but I cannot see why when I am explicity declaring that I dont care if any data goes missing, just chop the 32 bit into a 16 bit and I will be happy.
public void SetGreyscale(int channel, int percent)
{
// Calculate value in range of 0 through 4095 representing pwm greyscale data: refer to datasheet, 2^12 - 1
ushort value = (ushort)System.Math.Ceiling((double)percent * 40.95);
// determine the index position within GsData where our data starts
ushort quotient = ((12 * (ushort)(channel)) / 16); // There is 12 peices of 16 bits
I would prefer not to change int channel, to ushort channel. How can I solve the error?
(ushort) channel is ushort but 12 * (ushort)(channel) would be int, do this instead:
ushort quotient = (ushort) ((12 * channel) / 16);
Multiplication of any int and smaller types produces int. So in your case 12 * ushort produces int.
ushort quotient = (ushort)(12 * channel / 16);
Note that above code is not exactly equivalent to original sample - the cast of channel to ushort may significantly change result if value of channel is outside of ushort range (0.. 0xFFFF). In case if it is important you still need inner cast. Sample below will produce 0 for channel=0x10000 (which is what original sample in question does) unlike more regular looking code above (which gives 49152 result):
ushort quotient = (ushort)((12 * (ushort)channel) / 16);
Can anyone explain in a simple way the codes below:
public unsafe static float sample(){
int result = 154 + (153 << 8) + (25 << 16) + (64 << 24);
return *(float*)(&result); //don't know what for... please explain
}
Note: the above code uses unsafe function
For the above code, I'm having hard time because I don't understand what's the difference between its return value compare to the return value below:
return (float)(result);
Is it necessary to use unsafe function if your returning *(float*)(&result)?
On .NET a float is represented using an IEEE binary32 single precision floating number stored using 32 bits. Apparently the code constructs this number by assembling the bits into an int and then casts it to a float using unsafe. The cast is what in C++ terms is called a reinterpret_cast where no conversion is done when the cast is performed - the bits are just reinterpreted as a new type.
The number assembled is 4019999A in hexadecimal or 01000000 00011001 10011001 10011010 in binary:
The sign bit is 0 (it is a positive number).
The exponent bits are 10000000 (or 128) resulting in the exponent 128 - 127 = 1 (the fraction is multiplied by 2^1 = 2).
The fraction bits are 00110011001100110011010 which, if nothing else, almost have a recognizable pattern of zeros and ones.
The float returned has the exact same bits as 2.4 converted to floating point and the entire function can simply be replaced by the literal 2.4f.
The final zero that sort of "breaks the bit pattern" of the fraction is there perhaps to make the float match something that can be written using a floating point literal?
So what is the difference between a regular cast and this weird "unsafe cast"?
Assume the following code:
int result = 0x4019999A // 1075419546
float normalCast = (float) result;
float unsafeCast = *(float*) &result; // Only possible in an unsafe context
The first cast takes the integer 1075419546 and converts it to its floating point representation, e.g. 1075419546f. This involves computing the sign, exponent and fraction bits required to represent the original integer as a floating point number. This is a non-trivial computation that has to be done.
The second cast is more sinister (and can only be performed in an unsafe context). The &result takes the address of result returning a pointer to the location where the integer 1075419546 is stored. The pointer dereferencing operator * can then be used to retrieve the value pointed to by the pointer. Using *&result will retrieve the integer stored at the location however by first casting the pointer to a float* (a pointer to a float) a float is instead retrieved from the memory location resulting in the float 2.4f being assigned to unsafeCast. So the narrative of *(float*) &result is give me a pointer to result and assume the pointer is pointer to a float and retrieve the value pointed to by the pointer.
As opposed to the first cast the second cast doesn't require any computations. It just shoves the 32 bit stored in result into unsafeCast (which fortunately also is 32 bit).
In general performing a cast like that can fail in many ways but by using unsafe you are telling the compiler that you know what you are doing.
If i'm interpreting what the method is doing correctly, this is a safe equivalent:
public static float sample() {
int result = 154 + (153 << 8) + (25 << 16) + (64 << 24);
byte[] data = BitConverter.GetBytes(result);
return BitConverter.ToSingle(data, 0);
}
As has been said already, it is re-interpreting the int value as a float.
This looks like an optimization attempt. Instead of doing floating point calculations you are doing integer calculations on the Integer representation of a floating point number.
Remember, floats are stored as binary values just like ints.
After the calculation is done you are using pointers and casting to convert the integer into the float value.
This is not the same as casting the value to a float. That will turn the int value 1 into the float 1.0. In this case you turn the int value into the floating point number described by the binary value stored in the int.
It's quite hard to explain properly. I will look for an example. :-)
Edit:
Look here: http://en.wikipedia.org/wiki/Fast_inverse_square_root
Your code is basically doing the same as described in this article.
Re : What is it doing?
It is taking the value of the bytes stored int and instead interpreting these bytes as a float (without conversion).
Fortunately, floats and ints have the same data size of 4 bytes.
Because Sarge Borsch asked, here's the 'Union' equivalent:
[StructLayout(LayoutKind.Explicit)]
struct ByteFloatUnion {
[FieldOffset(0)] internal byte byte0;
[FieldOffset(1)] internal byte byte1;
[FieldOffset(2)] internal byte byte2;
[FieldOffset(3)] internal byte byte3;
[FieldOffset(0)] internal float single;
}
public static float sample() {
ByteFloatUnion result;
result.single = 0f;
result.byte0 = 154;
result.byte1 = 153;
result.byte2 = 25;
result.byte3 = 64;
return result.single;
}
As others have already described, it's treating the bytes of an int as if they were a float.
You might get the same result without using unsafe code like this:
public static float sample()
{
int result = 154 + (153 << 8) + (25 << 16) + (64 << 24);
return BitConverter.ToSingle(BitConverter.GetBytes(result), 0);
}
But then it won't be very fast any more and you might as well use floats/doubles and the Math functions.
I'm writing a datalog parser for a robot controller, and what's coming in from the data log is a number in the range of 0 - 65535 (which is a 16 bit unsigned integer if I'm not mistaken). I'm trying to convert that to a signed 16 bit integer to display to the user (since that was the actual datatype before the logger changed it).
Can someone give me a hand?
Example:
What the values should be
(0, -1, -2, -3, -4)
What the values are
(0, 65535, 65534, 65533, 65532)
Have you tried explicit casting?
UInt16 x = 65535;
var y = (Int16)x; // y = -1
Using unchecked here avoids a crash if [X] Check for Arithmetic Overflow is on:
UInt16 x = 65535;
Int16 y = unchecked((Int16)x);
Or like this
Just check if UI16>32767 if yes, I16=UI16-65536, otherwise = UI16
I receive an integer that represents a dollar amount in fractional denominations. I would like an algorithm that can add those numbers without parsing and converting them into doubles or decimals.
For example, I receive the integer 50155, which means 50 and 15.5/32 dollars. I then receive 10210 which is 10 and 21/32 dollars. So 50 15.5/32 + 10 21/32 = 61 4.5/32, thus:
50155 + 10210 = 61045
Again, I want to avoid this:
int a = 50155;
int b = a / 1000;
float c = a % 1000;
float d = b;
d += c / 320f;
// d = 50.484375
I would much prefer this:
int a = 50155;
int b = 10210;
int c = MyClass.Add(a.b); // c = 61045
...
public int Add(int a, int b)
{
// ?????
}
Thanks in advance for the help!
Well I don't think you need to use floating point...
public static int Add(int a, int b)
{
int firstWhole = a / 1000;
int secondWhole = b / 1000;
int firstFraction = a % 1000;
int secondFraction = b % 1000;
int totalFraction = firstFraction + secondFraction;
int totalWhole = firstWhole + secondWhole + (totalFraction / 320);
return totalWhole * 1000 + (totalFraction % 320);
}
Alternatively, you might want to create a custom struct that can convert to and from your integer format, and overloads the + operator. That would allow you to write more readable code which didn't accidentally lead to other integers being treated as this slightly odd format.
EDIT: If you're forced to stick with a "single integer" format but get to adjust it somewhat you may want to consider using 512 instead of 1000. That way you can use simple mask and shift:
public static int Add(int a, int b)
{
int firstWhole = a >> 9;
int secondWhole = b >> 9;
int firstFraction = a & 0x1ff
int secondFraction = b & 0x1ff;
int totalFraction = firstFraction + secondFraction;
int totalWhole = firstWhole + secondWhole + (totalFraction / 320);
return (totalWhole << 9) + (totalFraction % 320);
}
There's still the messing around with 320, but it's at least somewhat better.
Break the string up in the part that represents whole dollars, and the part that represents fractions of dollars. For the latter, instead of treating it as 10.5 thirty-seconds of a dollar, it's probably easier to treat it as 105 three hundred and twentieths of a dollar (i.e. multiply both by ten to the numerator is always an integer).
From there, doing math is fairly simple (if somewhat tedious to write): add the fractions. If that exceeds a whole dollar, carry a dollar (and subtract 320 from the fraction part). Then add the whole dollars. Subtraction likewise -- though in this case you need to take borrowing into account instead of carrying.
Edit:
This answer suggests that one "stays away" from float arithmetic. Surprisingly, the OP indicated that his float-based logic (not shown for proprietary reasons) was twice as fast as the integer-modulo solution below! Comes to show that FPUs are not that bad after all...
Definitively, stay away from floats (for this particular problem). Integer arithmetic is both more efficient and doesn't introduce rounding error issues.
Something like the following should do the trick
Note: As written, assumes A and B are positive.
int AddMyOddlyEncodedDollars (int A, int B) {
int sum;
sum = A + B
if (sum % 1000 < 320);
return sum
else
return sum + 1000 - 320;
}
Edit: On the efficiency of the modulo operator in C
I depends very much on the compiler... Since the modulo value is known at compile time, I'd expect most modern compilers to go the "multiply [by reciprocal] and shift" approach, and this is fast.
This concern about performance (with this rather contrived format) is a calling for premature optimization, but then again, I've seen software in the financial industry mightily optimized (to put it politely), and justifiably so.
As a point for learning, this representation is called "fixed point". There are a number of implementations that you can look at. I would strongly suggest that you do NOT use int as your top level data type, but instead create a type called Fixed that encapsulates the operations. It will keep your bug count down when you mistakenly add a plain int to a fixed point number without scaling it first, or scale a number and forget to unscale it.
Looks like a strange encoding to me.
Anyway, if the format is in 10-base Nxxx where N is an integer denoting whole dollars and xxx is interpreted as
(xxx / 320)
and you want to add them together, the only thing you need to handle is to do carry when xxx exceeds 320:
int a = ..., b = ...; // dollar amounts
int c = (a + b); // add together
// Calculate carry
int carry = (c % 1000) / 320; // integer division
c += carry * 1000;
c -= carry * 320;
// done
Note: this works because if a and b are encoded correctly, the fractional parts add together to 638 at most and thus there is no "overflow" to the whole dollars part.
BEWARE: This post is wrong, wrong, wrong. I will remove it as soon as I stop feeling a fool for trying it.
Here is my go: You can trade space for time.
Construct a mapping for the first 10 bits to a tuple: count of dollars, count of piecesof32.
Then use bit manipulation on your integer:
ignore bits 11 and above, apply map.
shift the whole number 10 times, add small change dollars from mapping above
you now have the dollar amoung and the piecesof32 amount
add both
move overflow to dollar amount
Next, to convert back to "canonical" notation, you need a reverse lookup map for your piecesof32 and "borrow" dollars to fill up the bits. Unshift the dollars 10 times and add the piecesof32.
EDIT: I should remove this, but I am too ashamed. Of course, it cannot work. I'm so stupid :(
The reason being: shifting by 10 to the right is the same as dividing by 1024 - it's not as if some of the lower bits have a dollar amount and some a piecesof32 amount. Decimal and binary notation just don't split up nicely. Thats why we use hexadecimal notation (grouping of 4 bits). Bummer.
If you insist on working in ints you can't solve your problem without parsing -- after all your data is not integer. I call into evidence the (so far) 3 answers which all parse your ints into their components before performing arithmetic.
An alternative would be to use rational numbers with 2 (integer) components, one for the whole part, and one for the number of 320ths in the fractional part. Then implement the appropriate rational arithmetic. As ever, choose your representations of data carefully and your algorithms become much easier to implement.
I can't say that I think this alternative is particularly better on any axis of comparison but it might satisfy your urge not to parse.