how do you set specific bits for a double?
For an int I'd do something like this:
public static int Value { get { return 0xfff8; } }
What should I do for double?
public static double Value { get { return 0xfff8; } }
I'm a bit concerned that I may get an implicit conversion from an int representation of 0xfff8 to the double floating point representation. However, I really want that 0xfff8 bit pattern regardless of the type.
Look at the BitConverter class or go unsafe.
Unsafe example (untested):
public unsafe double FromLong(long x)
{
return *((double*)&x);
}
BitConverter example:
double d = BitConverter.Int64BitsToDouble(0xdeadbeef);
http://msdn2.microsoft.com/en-us/library/system.bitconverter.int64bitstodouble
byte bTemp = Convert.ToByte(hexValueInString, 16);
double doubleTemp = Convert.ToDouble(bTemp);
I'm using .NET 4.0
Let's assume you have the following string 0x4007B425F202107B which represents double value.
To convert it to double (IEEE754 Double precision 64-bit), you need to use the following code:
var hex = "0x4007B425F202107B";
var int64Val = Convert.ToInt64(hex, 16);
var doubleVal = BitConverter.Int64BitsToDouble(int64Val);
Online converter from hex to double.
I just looked into the topic of converting a Hex string of a Double Value back into a Double Value.
I found some usefull sites.
This Site shows how to calculate a double value: https://gregstoll.dyndns.org/~gregstoll/floattohex/
This shows how decimal point fractals are calulated(binary excample) https://www.geeksforgeeks.org/convert-binary-fraction-decimal/
My example input value is 40C688C000000000, resulting in 11537.5
Important are the first 3 Hex Values, because they are the exponent used for the Double Value. The Amount of Hex Values after this doesn't really matter.
This is the simple Code I created from this Information:
public static double DoubleFromHex(string hex)
{
int exponent;
double result;
string doubleexponenthex = hex.Substring(0, 3);
string doublemantissahex = hex.Substring(3);
double mantissavalue = 1; //yes this is how it works
for (int i = 0; i < doublemantissahex.Length; i++)
{
int hexsignvalue = Convert.ToInt32(doublemantissahex.Substring(i, 1),16); //Convert ,16 Converts from Hex
mantissavalue += hexsignvalue * (1 / Math.Pow(16, i+1));
}
exponent = Convert.ToInt32(doubleexponenthex, 16);
exponent = exponent - 1023; //just how it works
result = Math.Pow(2, exponent) * mantissavalue;
return result;
}
Related
I have got a model which contains a property of data type decimal. I want to make sure the getter method returns a deterministic value in every case.
The data type model stores the number of non-significant decimal places, but does not seem to expose a method or property to control it.
The following program illustrates the findings:
class Program
{
static void Main(string[] args)
{
decimal d1 = decimal.Parse("1200.00");
Console.WriteLine(d1); // Prints 1200.00
decimal d2 = decimal.Parse("1200");
Console.WriteLine(d2); // Prints 1200
decimal d3 = correctDecimalPlaces(d2);
Console.WriteLine(d3); // Prints 1200.00
}
static decimal correctDecimalPlaces(decimal d)
{
return decimal.Parse(d.ToString("0.00"));
}
}
How can I control the number of decimal places used in decimal data type?
To change the number of decimal values, I convert the decimal to a string and back to a decimal. Do you know a cleaner way to do it?
Adding 0.00m to a decimal number, although counterintuitive, will force it to have at least 2 decimal points. If you need to ensure it has exactly 2, you can apply decimal.Round() also.
static decimal correctDecimalPlaces(decimal d)
{
return decimal.Round(d + 0.00m, 2);
}
I found this way (if return string is good for you):
public static class Extensions
{
public static string ToStringDecimal(this decimal d, byte decimals)
{
var fmt = (decimals>0) ? "0." + new string('0', decimals) : "0";
return d.ToString(fmt);
}
public static string ToStringDecimal(this decimal? d, byte decimals)
{
if (!d.HasValue) return "";
return ToStringDecimal(d.Value, decimals);
}
}
Or we use like this:
public static decimal? RoundTo2Decimal(decimal? pValue)
if (pValue.HasValue)
{
if (pValue.Value >= 0)
{
decimal vAluePos = pValue.Value * 100 + 0.5m;
return Math.Floor(vAluePos) / 100;
}
decimal vAlueNeg = Math.Abs(pValue.Value) * 100 + 0.5m;
return -(Math.Floor(vAlueNeg) / 100);
}
return null;
}
Is it possible in C# to format a double value with double.ToString in a way that I have always a fixed number of digits, no matter on which side of the decimal point?
Say I wish 6 digits, I want to have these results:
0.00123456789 gives "0.00123"
1.23456789 gives "1.23457"
123.456789 gives "123.457"
0.0000000123456789 gives "0.00000"
12345678.9 gives "12345679" (on overflow I want to see all digits left of decimalpoint)
4.2 gives "4.20000"
I'm experimenting with double.ToString, but cannot find any suitable format string.
Already tried "G6" (gives sometimes exponential format), "F6" (comes close, but 0.123456789 gives "0.123457" which are 7 digits).
I think some of your examples are wrong.
But I still think that I understand what you want to achieve.
I made an extension method.
public static class StringExtensionMethods
{
public static string ToString(this double d, int numberOfDigits)
{
var result = "";
// Split the number.
// Delimiter can vary depending on locale, should consider this and not use "."
string[] split = d.ToString().Split(new string[] { "." }, StringSplitOptions.None);
if(split[0].Count() >= numberOfDigits)
{
result = split[0].Substring(0, numberOfDigits);
}
else
{
result = split[0];
result += ".";
result += split[1];
// Add padding.
while(result.Count() < numberOfDigits +1)
result += "0";
result = result.Substring(0, numberOfDigits + 1);
}
return result;
}
}
I ran it with your examples:
double d0 = 0.00123456789;
double d1 = 1.23456789;
double d2 = 123.456789;
double d3 = 0.0000000123456789;
double d4 = 12345678.9;
double d5 = 4.2;
Console.WriteLine(d0.ToString(6));
Console.WriteLine(d1.ToString(6));
Console.WriteLine(d2.ToString(6));
Console.WriteLine(d3.ToString(6));
Console.WriteLine(d4.ToString(6));
Console.WriteLine(d5.ToString(6));
This is the output:
0.00123
1.23456
123.456
1.23456
123456
4.20000
I don't think this is the best way to solve it, but I like extension methods.
DoubleConverter class: http://1drv.ms/1yEbvL4
If your goal is to avoid "jumping" of the decimal point:
Use g formating, this does the most sensible thing to do
See where the decimal point is in your resulting string
pad with spaces at the beginning to align the column at the decimal point
As I understand, there is no predefined format that does what I need. So for everyone who is interested, here is the function I ended up with:
public string FormatValue(double d, int noOfDigits)
{
double abs = Math.Abs(d);
int left = abs < 1 ? 1 : (int)(Math.Log10(abs) + 1);
int usedDigits = 0;
StringBuilder sb = new StringBuilder();
for(; usedDigits < left; usedDigits++)
{
sb.Append("0");
}
if(usedDigits < noOfDigits)
{
sb.Append(".");
for(; usedDigits < noOfDigits; usedDigits++)
{
sb.Append("0");
}
}
return d.ToString(sb.ToString());
}
I have an input type integer that represents a number that needs to be converted to double between 1-100, and the rest is decimal precision.
Example: 1562 -> 15.62 ; 198912 -> 19.8912
Right now, I tried a conversion to string, count the number of characters, take 2 to check how many decimals I have and depending of the result "create" a composite string to get a valid double...
Any idea of there is a better way of resolving convert-precision on runtime.
What about this:
int value = 1562;
decimal d = value;
while (d > 100) {
d /= 10;
}
You can use LINQ Skip and Take like:
string str = "198912";
string newStr = string.Format("{0}.{1}", new string(str.Take(2).ToArray()), new string(str.Skip(2).ToArray()));
double d = double.Parse(newStr, CultureInfo.InvariantCulture);
You can add the checks for length on original string, and also use double.TryParse to see if you get valid values.
If you have an int to begin with then you can use decimal, which would provide you more accurate conversion. Like:
int number = 1562123123;
decimal decimalNumber = number;
while (decimalNumber > 100)
{
decimalNumber /= 10;
}
Here is a mathematical solution. The line lg = Math.Max(lg, 0); changes "2" to return "2.0" instead of "20.0" but I guess that depends on your needs for single digit numbers.
static double ToDoubleBetween1And100(int num)
{
var lg = Math.Floor(Math.Log10(num)) - 1;
lg = Math.Max(lg, 0);
return ((double)num) / Math.Pow(10, lg);
}
How to break a decimal value into integer values, first value should be the value before decimal and the other value of after decimal.
Problem : Decimal place is unknown as well as the number of digits;
ex :
double value = 2635.215;
int firstValue = 2635; // Should be
int secondValue = 215; // Should be
A possible solution:
using System.Globalization;
namespace DecimalSplit
{
class Program
{
static void Main(string[] args)
{
double value = 2635.215;
var values = value.ToString(CultureInfo.InvariantCulture).Split('.');
int firstValue = int.Parse(values[0]);
int secondValue = int.Parse(values[1]);
}
}
}
Using CultureInfo.InvariantCulture when converting to String will ensure that the decimal separator will be a . and the split will be done in the right place. In my culture the decimal separator was a , for example
You can use String.Split method for splitting a string. Convert double to string and then split it based on .
This problem is unsolvable, because a double value can have an extremely large number of decimal digits, so you cannot guarantee to be able to represent them in an integer. The closest I can give you is this, which works not with integers, but with doubles:
double left = System.Math.Floor(value);
double right = left - value;
Here is a little improvment of Răzvan Panda example.
An exception was raised in int secondValue = int.Parse(values[1]); if we parse a value with no decimal.
Another point is that it's better to have a string for the second value. See, example 3.
static void Main(string[] args)
{
double val1 = 2635.215;
Console.Out.WriteLine(GetFirstValue(val1)); // out 2635
Console.Out.WriteLine(GetSecondValue(val1)); // out 215
double val2 = 2;
Console.Out.WriteLine(GetFirstValue(val2)); // out 2
Console.Out.WriteLine(GetSecondValue(val2)); // out ''
double val3 = 3.04;
Console.Out.WriteLine(GetFirstValue(val3)); // out 3
Console.Out.WriteLine(GetSecondValue(val3)); // out 04
}
public static string GetFirstValue(double value)
{
var values = value.ToString(CultureInfo.InvariantCulture).Split('.');
return values[0];
}
public static string GetSecondValue(double value)
{
var values = value.ToString(CultureInfo.InvariantCulture).Split('.');
return values.Length > 1 ? values[1] : string.Empty;
}
try:
double value = 2635.215;
string a = value.ToString();
string[] b =a.Split('.');
int firstValue= int.Parse(b[0]);
int secondValue= int.Parse(b[1]);
You could do:
double decimalNumber = 123.456;
var numbersBeforeDecimalPoint = Math.Truncate(decimalNumber);
var numbersAfterDecimalPoint = decimalNumber - numbersBeforeDecimalPoint;
Using Math.Truncate we can get only the whole numbers, and we can then use that in tandem with our original number to get the decimal part.
This would give you 123 and 0.456 as a result.
Not sure if that's exactly what you're after (I appreciate you might want 123 and 456) - there are lots of good suggestions here for string manipulations to do it if you need more specific formatting.
I have to convert a double value x into two integers as specified by the following...
"x field consists of two signed 32 bit integers: x_i which represents the integral part and x_f which represents the fractional part multiplied by 10^8. e.g.: x of 80.99 will have x_i as 80 and x_f as 99,000,000"
First I tried the following, but it seems to fail sometimes, giving an xF value of 1999999 when it ought to be 2000000
// Doesn't work, sometimes we get 1999999 in the xF
int xI = (int)x;
int xF = (int)(((x - (double)xI) * 100000000));
The following seems to work in all the cases that I've tested. But I was wondering if there's a better way to do it without the round call. And also, could there be cases where this could still fail?
// Works, we get 2000000 but there's the round call
int xI = (int)x;
double temp = Math.Round(x - (double)xI, 6);
int xF = (int)(temp * 100000000);
The problem is (1) that binary floating point trades precision for range and (2) certain values, such as 3.1 cannot be repsented exactly in standard binary floating point formats, such as IEEE 754-2008.
First read David Goldberg's "What Every Computer Scientist Should Know About Floating-Point Arithmetic", published in ACM Computing Surveys, Vol 23, No 1, March 1991.
Then see these pages for more on the dangers, pitfalls and traps of using floats to store exact values:
http://steve.hollasch.net/cgindex/coding/ieeefloat.html
http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
Why roll your own when System.Decimal gives you precise decimal floating point?
But, if your going to do it, something like this should do you just fine:
struct WonkyNumber
{
private const double SCALE_FACTOR = 1.0E+8 ;
private int _intValue ;
private int _fractionalValue ;
private double _doubleValue ;
public int IntegralValue
{
get
{
return _intValue ;
}
set
{
_intValue = value ;
_doubleValue = ComputeDouble() ;
}
}
public int FractionalValue
{
get
{
return _fractionalValue ;
}
set
{
_fractionalValue = value ;
_doubleValue = ComputeDouble() ;
}
}
public double DoubleValue
{
get
{
return _doubleValue ;
}
set
{
this.DoubleValue = value ;
ParseDouble( out _intValue , out _fractionalValue ) ;
}
}
public WonkyNumber( double value ) : this()
{
_doubleValue = value ;
ParseDouble( out _intValue , out _fractionalValue ) ;
}
public WonkyNumber( int x , int y ) : this()
{
_intValue = x ;
_fractionalValue = y ;
_doubleValue = ComputeDouble() ;
return ;
}
private void ParseDouble( out int x , out int y )
{
double remainder = _doubleValue % 1.0 ;
double quotient = _doubleValue - remainder ;
x = (int) quotient ;
y = (int) Math.Round( remainder * SCALE_FACTOR ) ;
return ;
}
private double ComputeDouble()
{
double value = (double) this.IntegralValue
+ ( ( (double) this.FractionalValue ) / SCALE_FACTOR )
;
return value ;
}
public static implicit operator WonkyNumber( double value )
{
WonkyNumber instance = new WonkyNumber( value ) ;
return instance ;
}
public static implicit operator double( WonkyNumber value )
{
double instance = value.DoubleValue ;
return instance ;
}
}
I think using decimals solve the problem, because internally they really use a decimal representation of the numbers. With double you get rounding errors when converting the binary representation of a number to decimal. Try this:
double x = 1234567.2;
decimal d = (decimal)x;
int xI = (int)d;
int xF = (int)(((d - xI) * 100000000));
EDIT: The endless discussion with RuneFS shows that the matter is not that easy. Therefore I made a very simple test with one million iterations:
public static void TestDecimals()
{
int doubleFailures = 0;
int decimalFailures = 0;
for (int i = 0; i < 1000000; i++) {
double x = 1234567.7 + (13*i);
int frac = FracUsingDouble(x);
if (frac != 70000000) {
doubleFailures++;
}
frac = FracUsingDecimal(x);
if (frac != 70000000) {
decimalFailures++;
}
}
Console.WriteLine("Failures with double: {0}", doubleFailures); // => 516042
Console.WriteLine("Failures with decimal: {0}", decimalFailures); // => 0
Console.ReadKey();
}
private static int FracUsingDouble(double x)
{
int xI = (int)x;
int xF = (int)(((x - xI) * 100000000));
return xF;
}
private static int FracUsingDecimal(double x)
{
decimal d = (decimal)x;
int xI = (int)d;
int xF = (int)(((d - xI) * 100000000));
return xF;
}
In this Test 51.6% of the doubles-only conversion fail, where as no conversion fails when the number is converted to decimal first.
There are two issues:
Your input value will rarely be equal to its decimal representation with 8 digits after the decimal point. So some kind of rounding is inevitable. In other words: your number i.20000000 will actually be slightly less or slightly more than i.2.
Casting to int always rounds towards zero. This is why, if i.20000000 is less than i.2, you will get 19999999 for the fractional part. Using Convert.ToInt32 rounds to nearest, which is what you'll want here. It will give you 20000000 in all cases.
So, provided all your numbers are in the range 0-99999999.99999999, the following will always get you the nearest solution:
int xI = (int)x;
int xF = Convert.ToInt32((x - (double)xI) * 100000000);
Of course, as others have suggested, converting to decimal and using that for your calculations is an excellent option.