Break decimal value into two values (before and after decimal) - c#

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.

Related

Set the number of decimal places in data type decimal

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;
}

How to get selected number after decimal point

I have a double value for Example
0.0070
0.100
0.040
and I want output of above numbers as follows
70
100
40
Please guide me
Thanks
In theory this would be the way to do it
double number = 0.0070
string num = number.ToString(); //Convert to string
int index = num.IndexOf('.') + 1; //Find the decimal
string trunc = num.Substring(index); //Get rid of everything before it
trunc.TrimStart('0'); //Get rid of leading zeros
double result = Convert.ToDouble(trunc); //Convert back to double
However, C# does not respect trailing zeros in numerical values so as soon as you say 0.0070 into a double it is truncated to 0.007
public int getTheNumberAfterDecimalPoint(double number)
{
string numberInString = Convert.ToString(number);
if(numberInString.Contains('.'))
{
return Convert.ToInt32(numberInString.Substring('.')[1]);
}
return Convert.ToInt32(number);
}

How to format floating point value with fix number of digits?

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());
}

String/Int to double with precision defined onruntime

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);
}

Convert Hex to Double

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;
}

Categories