I need to convert 2 integers to a float number. I'm using the following function to do this conversion:
string hexString = value1 + value2;
uint num = uint.Parse(hexString, NumberStyles.AllowHexSpecifier);
byte[] floatVals = BitConverter.GetBytes(num);
f = BitConverter.ToSingle(floatVals, 0);
The function works fine, except when the second integer is negative. Which gives a small difference in the decimal part.
Example:
16998 and 16673: 57.76 -> Correct
16998 and -11174: 57.54 -> Incorrect (The correct is: 57.71).
What I'm doing to get close to the correct number is multiplying the second integer by -1 to make it positive. My question is how to get the exact value when the second integer is negative?
Reading the manual, it says:
Myy app screenshot:
Related
I'm trying t wrap my mind around the float behavior (in C#). I have take notice of the floating point precision issue thingy.
I want to convert an floating point string to an float, add + 1 to it and convert it back to a string. The input can be with (never more then 5 decimal places) or without decimals, this is different every time. The output has to be again the full notation (no Scientific notation like: 2.017002E+09F)
It seems to work correctly with the decimal conversion.
Any suggestions for the best practice to get it working with a float?
var inputDecimalStr = "2017002005"; //2017002005.55 has the same result for the float conversion
float floatRegNr = 0;
float.TryParse(inputDecimalStr, out floatRegNr); // somehow this converts to 2.017002E+09
decimal test1 = decimal.Parse(inputDecimalStr); // this seems to work
float test2 = Convert.ToSingle(test1); // somehow this converts to 2.017002E+09
float test3 = Single.Parse(inputDecimalStr, NumberStyles.Float, CultureInfo.InvariantCulture);
float test4 = 2017002005F;
float test5 = 2.017002E+09F;
float test6 = 2.017002005E+09F;
double test7 = 234423.33D;
//this works ok
test5.ToString("0." + new string('#', 339));
test1.ToString();
If you use this tool that shows you the binary representation of float, you get that 2017002005 is represented as 0x4ef07204, which translated back to decimal form becomes 2017001984 (an error of 21 out of the conversion).
If you change the least significative bit of the number (i.e. the minimum change that can be registered) you get 0x4ef07205, which represents 2017002112 (107 more than 2017002005 + 1.
If this level of detail is important, you can use fixed point arithmetic. Since you only want to add 1, split the number into integer and decimal parts, add 1 to the integer part and then convert back to String each part separately.
Here is the code which made me post this question.
// int integer;
// int fraction;
// double arg = 110.1;
this.integer = (int)(arg);
this.fraction = (int)((arg - this.integer) * 100);
The variable integer is getting 110. That's OK.
The variable fraction is getting 9, however I am expecting 10.
What is wrong?
Update
It seems I have discovered that the source of the problem is subtraction
arg - this.integer
Its result is 0.099999999999994316.
Now I am wondering how I should correctly subtract so that the result was 0.1.
You have this:
fraction = (int)((110.1 - 110) * 100);
The inner part ((110.1 - 110) * 100), will be 9.999999
When you cast it to int, it will be round off to 9
This is because of "floating point" (see here) limitations:
Computers always need some way of representing data, and ultimately
those representations will always boil down to binary (0s and 1s).
Integers are easy to represent, but non-integers are a bit more
tricky. Consider the following var:
double x = 0.1d;
The variable x will actually store the closest available double to
that value. When you understand this, it becomes obvious why some
calculations seem to be "wrong".
If you were asked to add a third to a third, but could only use 3
decimal places, you'd get the "wrong" answer: the closest you could
get to a third is 0.333, and adding two of those together gives 0.666,
rather than 0.667 (which is closer to the exact value of two thirds).
Update:
In financial applications or where the numbers are so important to be exact, you can use decimal data type:
(int)((110.1m - 110) * 100) //will be 10 (m is decimal symbol)
or:
decimal arg = 110.1m;
int integer = (int)(arg); //110
decimal fraction = (int)((arg - integer) * 100); //will be 10
It is because you are using double, precision gets rounded, if you want it to be 10 use decimal type:
check the following:
int integer;
int fraction;
decimal arg = 110.1M;
integer = (int)(arg);
decimal diff = arg - integer;
decimal multiply = diff * 100;
fraction = (int)multiply;//output will be 10 as you expect
I have to convert an object to int. My object values is something like 1.34535
What I need is the first part which is (1).
I tried the followings:
- Convert.ToInt32(myObj.Value), it rounds the number. if it's 1.78, I got it (2) which is wrong. I need only the integer of first part.
int.TryParse(myObj.Value.toString(), out outValue)
I got it 0 for all values!
int.Parse(myObj.Value.toString()) throws an exception, that is in incorrect format.
If myObj.Value is boxed double then you have to cast twice: to unbox back into double and then in order to truncate into int:
int result = (int)((double)(myObj.Value)):
In general case, try Convert; the idea is the same: first restore the orignal double and then obtain required int:
int result = (int) (Convert.ToDouble(myObj.Value));
Edit: in the implementation above I've read without rounding request as truncated, i.e. fractional part should be ignored:
2.4 -> 2
-2.4 -> -2
If different behaviour is expected, e.g.
2.4 -> 2
-2.4 -> -3
one can add Math.Floor e.g.
int result = (int) (Math.Floor(Convert.ToDouble(myObj.Value)));
Convert to double it first;
var doubleValue = double.Parse(myObj.Value.ToString());
//It could be better to use double.TryParse
int myInt = (int)Math.Floor(doubleValue);
Convert your object to a double value and use Use Math.Truncate(number)
http://msdn.microsoft.com/en-us/library/c2eabd70.aspx
Very easy, don't forget to wrap it in try and catch:
int i = (int)Math.Truncate(double.Parse(myObj.ToString()));
Math.Truncate just cuts off the numbers after the comma like:
4.434 becomes 4
-43.65445 becomes -43
Perhaps, this is also a solution :
var integer = int.Parse(myObject.Value.ToString().Split('.').First());
I have the following operation in PHP:
24733 * 0x41c64e6d + 0x6073;
...and the result is: 27293242579276
With the same logic, I do the same operation in C#:
24733 * 0x41c64e6d + 0x6073;
But the result is: -1274586804
OMG, why?
by default c# treats number as int when no explicit cast is specified.
so 24733 is treated as int.
int x int + int = int
and Max int is 2147483647 which is way smaller than 27293242579276. This resulted in integer overflow.
To solve the problem, use a type with higher number of bits such as decimal
you can append a letter "m" at the end of the number to tell c# you want it to be a decimal
like 24733m * 0x41c64e6d + 0x6073
In PHP here's what's happening
int(24733) *
int(1103515245) +
int(24691)
You can see this by doing a var_dump of the values
In 64-bit builds, the maximum integer is 9223372036854775807. So PHP can support the provided answer of 27293242579276. Based on the other answer, it looks like C# just converts the numbers differently, and possibly with a lower maximum integer.
I'm trying to convert a string that includes a hex value into its equivalent signed short in C#
for example:
the equivalent hex number of -1 is 0xFFFF (in two bytes)
I want to do the inverse, i.e I want to convert 0xFFFF into -1
I'm using
string x = "FF";
short y = Convert.ToInt16(x,16);
but the output y is 255 instead of -1, I need the signed number equivalent
can anyone help me?
thanks
When your input is "FF" you have the string representation in hex of a single byte.
If you try to assign it to a short (two bytes), the last bit is not considered for applying the sign to the converted number and thus you get the 255 value.
Instead a string representation of "FFFF" represents two bytes where the last bit is set to 1 so the result, if assigned to a signed type like Int16, is negative while, if assigned to an unsigned type like ushort, is 65535-
string number = "0xFFFF";
short n = Convert.ToInt16(number, 16);
ushort u = Convert.ToUInt16(number, 16);
Console.WriteLine(n);
Console.WriteLine(u);
number = "0xFF";
byte b = Convert.ToByte(number, 16);
short x = Convert.ToInt16(number, 16);
ushort z = Convert.ToUInt16(number, 16);
Console.WriteLine(n);
Console.WriteLine(x);
Console.WriteLine(z);
Output:
-1
65535
-1
255
255
You're looking to convert the string representation of a signed byte, not short.
You should use Convert.ToSByte(string) instead.
A simple unit test to demonstrate
[Test]
public void MyTest()
{
short myValue = Convert.ToSByte("FF", 16);
Assert.AreEqual(-1, myValue);
}
Please see http://msdn.microsoft.com/en-us/library/bb311038.aspx for full details on converting between hex strings and numeric values.