C# double to integer - c#

Lets say I have the double 42.433243 and I would like to convert it to the integer 42433243.
What is the code for doing that when the decimal length is random?
Further examples:
45.25 => 4525
125.152254 => 125152254
etc...

You can multiply the value by 10 as long as there are any fraction part:
Decimal m = 42.433243m;
while (m % 1 != 0) m *= 10;
int i = (int)m;

Quick and dirty:
double x = 42.25;
int big = int.Parse(x.ToString().Replace(".",""));
This doesn't work if the number is too big (e.g. overflow, bigger than 2^32 for int, or you could replace int with double on line 2 and get it a lot larger).
Let me know if you have other considerations.

Perhaps something like this would work.
while ((double_num - Math.floor(double_num)) != 0.0) double_num *= 10;
int num = (int) double_num;

int result = Convert.ToInt32(Regex.Match(digits.Replace(".","").Replace(",",""), #"^\d+$").Value);

A more direct way to do this would be to convert the number to a decimal and examine the bits.
The first 96 least-significant bits represents the mantissa while the 32 most-significant bits represents the exponent. So the actual value that you would be interested in is the 32 least significant bits. The Decimal.GetBits() method returns the bits as an array ints so all you need to do is grab the first int in the array. As long as the numbers don't exceed int.MaxValue, you're golden.
var number = 42.433243;
var asDecimal = (Decimal)number;
var bits = Decimal.GetBits(asDecimal);
var digits = bits[0]; // 42433243

Related

Display very Large or Small Numbers in Scientific Notation by Counting the Zero's

I need a method to get the number of Zeros AFTER the Decimal point when the number BEFORE the decimal point is also Zero. So For example 0.00000000987654 would work out as 8, since there are 8 Zero's after 0. Turning the Decimal Data type into a string I could then display this in Scientific Notation as 9.87654E9.
The reason I need to do this is so I can iterate very small numbers multiple times producing results too high for calculators.
So for example 0.123456789 Multiplied by 0.1 and iterated a 1000 times. (0.123456789 * 0.1 * 0.1 * 0.1 * 0.1 ......) works out at 1.234567890000000000000000000E-1001 using the Decimal Data Type with the full 28-digit precision and displayed in Scientific Notation
I was able to achieve this when working with Factorials. For Example the Factorial of 1000 is 1000 x 999 * 998 * 997 * 996 .... all the way down to 0. This number is too high for calculators so I used iteration to achieve the result to 28-digit precision in Scientific Notation.
For the very large numbers I was successful. I achieved this by getting the number of Digits BEFORE the period:
static int Get_Digits_Before_Period(decimal Large_Number)
{
decimal d = decimal.Floor(Large_Number < 0 ? decimal.Negate(Large_Number) : Large_Number);
// 0.xyz should return 0, therefore a special case
if (d == 0m)
return 0;
int cnt = 1;
while ((d = decimal.Floor(d / 10m)) != 0m)
cnt++;
return cnt;
}
I now need a similar method but one for obtaining the number of Zero's AFTER the period.
The exponent range for decimal is 0 ~ -28, so it cannot represent a number such as 1.234567890000000000000000000E-1001, so I just explain numbers in the valid ranges.
To count the ZERO for a decimal, you can fetch the integer and exponent part of the decimal first
var number = 0.00000000987654m;
var bits = decimal.GetBits(number); //0~2 are integer part.
var exponent = (bits[3] & 0xff0000) >> 16;
Then reduce exponent by significant digits of the integers to get zero count after the period.
var zeros = exponent;
for(int i = 0; i <= 2; i++)
{
if(bits[i] != 0)
zeros -= (int)Math.Log10(bits[i]) + 1;
}
if(zeros < 0)
zeros = 0;

Get Integer and Fractional part of a decimal number

Given X.Y, I want to get X and Y.
For instance, given 123.456 I want to get 123 and 456 (NOT 0.456).
I can do the following:
decimal num = 123.456M;
decimal integer = Math.Truncate(num);
decimal fractional = num - Math.Truncate(num);
// integer = 123
// fractional = 0.456 but I want 456
REF
As above-mentioned, using this method I will get 0.456, while I need 456. Sure I can do the following:
int fractionalNums = (int)((num - Math.Truncate(num)) * 1000);
// fracionalNums = 456
Additionally, this method requires knowing how many fractional numbers a given decimal number has so that you can multiply to that number (e.g., 123.456 has three, 123.4567 has four, 123.456789 has six, 123.1234567890123456789 has nineteen).
Few points to consider:
This operation will be executed millions of times; hence, performance is critical (maybe a bit-wise-based solution would do better);
Precision is critical, and no rounding is acceptable.
NOTE 1
For performance reasons, I am NOT interested in string manipulation-based approaches.
NOTE 2
The numbers in my question are of decimal type, hence methods that work for only decimal types and fail on float or double (due to floating point precision) are acceptable.
NOTE 3
Two sides of decimal (i.e., integer and fractional parts) can be considered two integers. Hence, 123.000456 is not an expected input; and even if it is given, it is acceptable to split it to 123 and 456 (because both sides are to be considered integers).
BitConverter.GetBytes(decimal.GetBits(num)[3])[2]; - number of digits after comma
long[] tens = new long[] {1, 10, 100, 1000, ...};
decimal num = 123.456M;
int iPart = (int)num;
decimal dPart = num - iPart;
int count = BitConverter.GetBytes(decimal.GetBits(num)[3])[2];
long pow = tens[count];
Console.WriteLine(iPart);
Console.WriteLine((long)(dPart * pow));
Decimal has a 96 bit mantissa, so a long is not good enough to get every possible value.
Define all (positive) powers of 10 defined for Decimal:
decimal mults[] = {1M, 1e1M, 1e2M, 1e3M, <insert rest here>, 1e27M, 1e28M};
Then, inside the loop you need to get the scale (the power of 10 by which the "mantissa" is divided to get the nominal value of the decimal):
int[] bits = Decimal.GetBits(n);
int scale = (bits[3] >> 16) & 31; // 567.1234 represented as 5671234 x 10^-4
decimal intPart = (int)n; // 567.1234 --> 567
decimal decPart = (n - intPart) * mults[scale]; // 567.1234 --> 0.1234 --> 1234
The easiest way is probably to convert the number to string.
Then take the substring after the decimal point, and convert it back to int.

How to (theoretically) print all possible double precision numbers in C#?

For a little personal research project I want to generate a string list of all possible values a double precision floating point number can have.
I've found the "r" formatting option, which guarantees that the string can be parsed back into the exact same bit representation:
string s = myDouble.ToString("r");
But how to generate all possible bit combinations? Preferably ordered by value.
Maybe using the unchecked keyword somehow?
unchecked
{
//for all long values
myDouble[i] = myLong++;
}
Disclaimer: It's more a theoretical question, I am not going to read all the numbers... :)
using unsafe code:
ulong i = 0; //long is 64 bit, like double
unsafe
{
double* d = (double*)&i;
for(;i<ulong.MaxValue;i++)
Console.WriteLine(*d);
}
You can start with all possible values 0 <= x < 1. You can create those by having zero for exponent and use different values for the mantissa.
The mantissa is stored in 52 bits of the 64 bits that make a double precision number, so that makes for 2 ^ 52 = 4503599627370496 different numbers between 0 and 1.
From the description of the decimal format you can figure out how the bit pattern (eight bytes) should be for those numbers, then you can use the BitConverter.ToDouble method to do the conversion.
Then you can set the first bit to make the negative version of all those numbers.
All those numbers are unique, beyond that you will start getting duplicate values because there are several ways to express the same value when the exponent is non-zero. For each new non-zero exponent you would get the value that were not possible to express with the previously used expontents.
The values between 0 and 1 will however keep you busy for the forseeable future, so you can just start with those.
This should be doable in safe code: Create a bit string. Convert that to a double. Output. Increment. Repeat.... A LOT.
string bstr = "01010101010101010101010101010101"; // this is 32 instead of 64, adjust as needed
long v = 0;
for (int i = bstr.Length - 1; i >= 0; i--) v = (v << 1) + (bstr[i] - '0');
double d = BitConverter.ToDouble(BitConverter.GetBytes(v), 0);
// increment bstr and loop

Percentile algorithm

I am writing a program that finds percentile. According to eHow:
Start to calculate the percentile of your test score (as an example we’ll stick with your score of 87). The formula to use is L/N(100) = P where L is the number of tests with scores less than 87, N is the total number of test scores (here 150) and P is the percentile. Count up the total number of test scores that are less than 87. We’ll assume the number is 113. This gives us L = 113 and N = 150.
And so, according to the instructions, I wrote:
string[] n = Interaction.InputBox("Enter the data set. The numbers do not have to be sorted.").Split(',');
List<Single> x = new List<Single> { };
foreach (string i in n)
{
x.Add(Single.Parse(i));
}
x.Sort();
List<double> lowerThan = new List<double> { };
Single score = Single.Parse(Interaction.InputBox("Enter the number."));
uint length = (uint)x.Count;
foreach (Single index in x)
{
if (index > score)
{
lowerThan.Add(index);
}
}
uint lowerThanCount = (uint)lowerThan.Count();
double percentile = lowerThanCount / length * 100;
MessageBox.Show("" + percentile);
Yet the program always returns 0 as the percentile! What errors have I made?
Your calculation
double percentile = lowerThanCount / length * 100;
is all done in integers, since the right hand side consist of all integers. Atleast one of the operand should be of floating point type. So
double percentile = (float) lowerThanCount / length * 100;
This is effectively a rounding problem, lowerThanCount / length are both unit therefore don't support decimal places so any natural percentage calculation (e.g. 0.2/0.5) would result in 0.
For example, If we were to assume lowerThanCount = 10 and length = 20, the sum would look something like
double result = (10 / 20) * 100
Therefore results in
(10 / 20) = 0.5 * 100
As 0.5 cannot be represented as an integer the floating point is truncated which leaves you with 0, so the final calculation eventually becomes
0 * 100 = 0;
You can fix this by forcing the calculation to work with a floating point type instead e.g.
double percentile = (double)lowerThanCount / length * 100
In terms of readability, it probably makes better sense to go with the cast in the calculation given lowerThanCount & length won't ever naturally be floating point numbers.
Also, your code could be simplified a lot using LINQ
string[] n = Interaction.InputBox("Enter the data set. The numbers do not have to be sorted.")
.Split(',');
IList<Single> x = n.Select(n => Single.Parse(n))
.OrderBy(x => x);
Single score = Single.Parse(Interaction.InputBox("Enter the number."));
IList<Single> lowerThan = x.Where(s => s < score);
Single percentile = (Single)lowerThan.Count / x.Count;
MessageBox.Show(percentile.ToString("%"));
The problem is in the types that you used for your variables: in this expression
double percentile = lowerThanCount / length * 100;
// ^^^^^^^^^^^^^^^^^^^^^^^
// | | |
// This is integer division; since length > lowerThanCount, its result is zero
the division is done on integers, so the result is going to be zero.
Change the type of lowerThanCount to double to fix this problem:
double lowerThanCount = (double)lowerThan.Count();
You are using integer division instead of floating point division. Cast length/lowerThanCount to a float before dividing.
Besides the percentile calculation (should be with floats), I think your count is off here:
foreach (Single index in x)
{
if (index > score)
{
lowerThan.Add(index);
}
}
You go through indexes and if they are larger than score, you put them into lowerThan
Just a logical mistake?
EDIT: for the percentile problem, here is my fix:
double percentile = ((double)lowerThanCount / (double)length) * 100.0;
You might not need all the (double)'s there, but just to be safe...

custom method for returning decimal places shows odd behavior

I am writing a simple method that will calculate the number of decimal places in a decimal value. The method looks like this:
public int GetDecimalPlaces(decimal decimalNumber) {
try {
int decimalPlaces = 1;
double powers = 10.0;
if (decimalNumber > 0.0m) {
while (((double)decimalNumber * powers) % 1 != 0.0) {
powers *= 10.0;
++decimalPlaces;
}
}
return decimalPlaces;
I have run it against some test values to make sure that everything is working fine but am getting some really weird behavior back on the last one:
int test = GetDecimalPlaces(0.1m);
int test2 = GetDecimalPlaces(0.01m);
int test3 = GetDecimalPlaces(0.001m);
int test4 = GetDecimalPlaces(0.0000000001m);
int test5 = GetDecimalPlaces(0.00000000010000000001m);
int test6 = GetDecimalPlaces(0.0000000001000000000100000000010000000001000000000100000000010000000001000000000100000000010000000001m);
Tests 1-5 work fine but test6 returns 23. I know that the value being passed in exceeds the maximum decimal precision but why 23? The other thing I found odd is when I put a breakpoint inside the GetDecimalPlaces method following my call from test6 the value of decimalNumber inside the method comes through as the same value that would have come from test5 (20 decimal places) yet even though the value passed in has 20 decimal places 23 is returned.
Maybe its just because I'm passing in a number that has way too many decimal places and things go wonky but I want to make sure that I'm not missing something fundamentally wrong here that might throw off calculations for the other values later down the road.
The number you're actually testing is this:
0.0000000001000000000100000000
That's the closest exact decimal value to 0.0000000001000000000100000000010000000001000000000100000000010000000001000000000100000000010000000001.
So the correct answer is actually 20. However, your code is giving you 23 because you're using binary floating point arithmetic, for no obvious reason. That's going to be introducing errors into your calculations, completely unnecessarily. If you change to use decimal consistently, it's fine:
public static int GetDecimalPlaces(decimal decimalNumber) {
int decimalPlaces = 1;
decimal powers = 10.0m;
if (decimalNumber > 0.0m) {
while ((decimalNumber * powers) % 1 != 0.0m) {
powers *= 10.0m;
++decimalPlaces;
}
}
return decimalPlaces;
}
(Suggestion) You could calculate that this way:
public static int GetDecimalPlaces(decimal decimalNumber)
{
var s = decimalNumber.ToString();
return s.Substring(s.IndexOf(CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator) + 1).Length;
}
There is another way to do this and probably it works faster because it uses remainder operation only if the decimal number has a "trailing zeros" problem.
The basic idea:
In .NET any decimal is stored in memory in the form
m * Math.Power(10, -p)
where m is mantissa (96 bit size) and p is order (value from 0 to 28).
decimal.GetBits method retrieves this representation from decimal struct and returns it as array of int (of length 4).
Using this data we can construct another decimal. If we will use only mantissa, without "Math.Power(10, -p)" part, the result will be an integral decimal. And if this integral decimal number is divisible by 10, then our source number has one or more trailing zeros.
So here is my code
static int GetDecimalPlaces(decimal value)
{
// getting raw decimal structure
var raw = decimal.GetBits(value);
// getting current decimal point position
int decimalPoint = (raw[3] >> 16) & 0xFF;
// using raw data to create integral decimal with the same mantissa
// (note: it always will be absolute value because I do not analyze
// the sign information of source number)
decimal integral = new decimal(raw[0], raw[1], raw[2], false, 0);
// disposing from trailing zeros
while (integral > 0 && integral % 10 == 0)
{
decimalPoint--;
integral /= 10;
}
// returning the answer
return decimalPoint;
}

Categories

Resources