Get the decimal part from a double
Asked Answered
A

18

115

I want to receive the number after the decimal dot in the form of an integer. For example, only 05 from 1.05 or from 2.50 only 50 not 0.50

Amando answered 23/10, 2012 at 20:13 Comment(9)
2.50 is just 2.5. I assume you're talking of strings.Boger
Are you always returning the first two digits after the decimal place? Is the input a decimal, float, string, ...?Marcellmarcella
An example of usages goes a long way toward getting quality answers, for next time.Blocker
yes only towo digits ,the input is decimalAmando
Why not use int y = value.Split('.')[1];?There
@SearchForKnowledge, . is different in some countries.Transversal
@There also performing split would take more time than mathematical expressionsTiffanytiffi
The C# development team should be embarrassed (and take action) that this very common operation has no single Math.function such as Math.DecimalPart(double x) or something. There is way too much "did you try this, did you think about that" for something many of us need to do often.Hillell
Meta observation: Not getting a "0.50" but getting a number of "50" from "2.50", or getting a number of "05" is one of the most ill-specified requirements I heard or read today.. not mentioning misleading title of the question. That being said, it's interesting how many of the answers focus on the title and focus on how to calculate the non-integral part of a floating number, completely ignoring that the actual question includes quite specific formatting requirements :) Congrats to orad for answering in full.Bayer
G
247

the best of the best way is:

var floatNumber = 12.5523;

var x = floatNumber - Math.Truncate(floatNumber);

result you can convert however you like

Goggles answered 3/9, 2014 at 10:23 Comment(5)
This should be the accepted answer, a Math solution to a Math question, without all that tedious mucking about in string manipulationBillowy
I think this solution have a "problem". If the floatNumber was "10.2", the variable x will be something like "0.19999999999999929". Even if this works as expected, the result would be "0.2" and not "2".Hardunn
@Hardunn Float and Double values always have small errors under subtraction in the last few decimal places. You should not be considering those as significant. If you actually need that kind of precision, you should be using Decimal type. If you can't switch to Decimal (or just don't want to), then you ought to keep track of the expected precision somehow and account for that in comparison operations. I usually use 4 decimal places, but there may be exceptions to that.Hillell
From msdn.microsoft.com/en-us/library/… : "Because some numbers cannot be represented exactly as fractional binary values, floating-point numbers can only approximate real numbers"Hillell
Final comment: Using Math.Truncate was the intent of the author's of the Math library for this kind of situation. @Matterai 's answer should be the accepted one.Hillell
B
88
var decPlaces = (int)(((decimal)number % 1) * 100);

This presumes your number only has two decimal places.

Blocker answered 23/10, 2012 at 20:16 Comment(2)
(318.40d % 1) * 100 outputs 39.9999999999977, you can use casting to get around the rounding error: var decPlaces = (int)(((decimal)number % 1) * 100);Ayer
@Ayer Good call there - floating point numbers always have these little inaccuracies, so casting it is pretty prudent to ensure consistent behavior. I'll update my answer, though Matterai's is still more technically correct.Blocker
F
68

There is a cleaner and ways faster solution than the 'Math.Truncate' approach:

double frac = value % 1;
Forfeit answered 3/7, 2018 at 23:27 Comment(1)
a note: for negative values, it is negative: -12.34 % 1 => -0.33999999999999986Fra
A
19

Solution without rounding problem:

double number = 10.20;
var first2DecimalPlaces = (int)(((decimal)number % 1) * 100);
Console.Write("{0:00}", first2DecimalPlaces);

Outputs: 20

Note if we did not cast to decimal, it would output 19.

Also:

  • for 318.40 outputs: 40 (instead of 39)
  • for 47.612345 outputs: 61 (instead of 612345)
  • for 3.01 outputs: 01 (instead of 1)

If you are working with financial numbers, for example if in this case you are trying to get the cents part of a transaction amount, always use the decimal data type.

Update:

The following will also work if processing it as a string (building on @SearchForKnowledge's answer).

10.2d.ToString("0.00", CultureInfo.InvariantCulture).Split('.')[1]

You can then use Int32.Parse to convert it to int.

Ayer answered 13/7, 2015 at 18:47 Comment(2)
Thumbs up for mod onesStefansson
I used this...10.2d.ToString("0.00", CultureInfo.InvariantCulture).Split('.')[1]Mejia
E
11

Better Way -

        double value = 10.567;
        int result = (int)((value - (int)value) * 100);
        Console.WriteLine(result);

Output -

56
Envious answered 23/10, 2012 at 20:22 Comment(2)
Did not test, but this suffers from float inaccuracy, no?Teeny
For 10.20 it will output 19. See my answer.Ayer
E
9

The simplest variant is possibly with Math.truncate()

double value = 1.761
double decPart = value - Math.truncate(value)
Ejection answered 5/8, 2015 at 12:1 Comment(1)
does not work for value below zero like 0.25Fiber
D
6

I guess this thread is getting old but I can't believe nobody has mentioned Math.Floor

//will always be .02 cents
(10.02m - System.Math.Floor(10.02m))
Deration answered 19/12, 2019 at 21:17 Comment(1)
For the super lazy: double fract(double x) { return x - System.Math.Floor(x); }Bedazzle
B
2
var result = number.ToString().Split(System.Globalization.NumberDecimalSeparator)[2]

Returns it as a string (but you can always cast that back to an int), and assumes the number does have a "." somewhere.

Byplay answered 23/10, 2012 at 20:18 Comment(0)
W
1
int last2digits = num - (int) ((double) (num /  100) * 100);
Wynd answered 2/4, 2015 at 4:59 Comment(1)
Question is to get first 2 decimal digits. For number 318.401567d your solution outputs 0.401567 where 40 is expected.Ayer
N
0
    public static string FractionPart(this double instance)
    {
        var result = string.Empty;
        var ic = CultureInfo.InvariantCulture;
        var splits = instance.ToString(ic).Split(new[] { ic.NumberFormat.NumberDecimalSeparator }, StringSplitOptions.RemoveEmptyEntries);
        if (splits.Count() > 1)
        {
            result = splits[1];
        }
        return result;
    }
Nynorsk answered 10/11, 2013 at 20:12 Comment(0)
Z
0
 string input = "0.55";
    var regex1 = new System.Text.RegularExpressions.Regex("(?<=[\\.])[0-9]+");
    if (regex1.IsMatch(input))
    {
        string dp= regex1.Match(input ).Value;
    }
Zomba answered 9/11, 2020 at 12:38 Comment(1)
It would be awesome if you could add a description on how the regex helps solving the problemEcumenicist
D
0

In my tests this was 3-4 times slower than the Math.Truncate answer, but only one function call. Perhaps someone likes it:

var float_number = 12.345;
var x = Math.IEEERemainder(float_number , 1)
Deejay answered 26/4, 2021 at 14:56 Comment(0)
M
0
var d = 1.5;
var decimalPart = Convert.ToInt32(d.ToString().Split('.')[1]);

it gives you 5 from 1.5 :)

Microparasite answered 25/10, 2021 at 20:48 Comment(6)
This will give you 25 for 0.25 thoughUrbannai
@Urbannai as the question wants :)Microparasite
No, he wants 50 for 0.5Urbannai
@Urbannai no, he wants 50 from 2.50Microparasite
There is no difference between 2.5 and 2.50Urbannai
its from the question: For example, only 05 from 1.05 or from 2.50 only 50 not 0.50Microparasite
E
-1

You may remove the dot . from the double you are trying to get the decimals from using the Remove() function after converting the double to string so that you could do the operations required on it

Consider having a double _Double of value of 0.66781, the following code will only show the numbers after the dot . which are 66781

double _Double = 0.66781; //Declare a new double with a value of 0.66781
string _Decimals = _Double.ToString().Remove(0, _Double.ToString().IndexOf(".") + 1); //Remove everything starting with index 0 and ending at the index of ([the dot .] + 1) 

Another Solution

You may use the class Path as well which performs operations on string instances in a cross-platform manner

double _Double = 0.66781; //Declare a new double with a value of 0.66781
string Output = Path.GetExtension(D.ToString()).Replace(".",""); //Get (the dot and the content after the last dot available and replace the dot with nothing) as a new string object Output
//Do something
Epoch answered 23/10, 2012 at 20:22 Comment(0)
P
-1

My answer is based on a suspected use-case behind this question and people coming to this question.

The following example program will display a decimal value in a way that appears like a currency like 34.99 or 1.00 unless it has further precision, in which case it will display the whole precision like, 290.19882 or 128.00001

Please critique. Remember the design is for display.

using System;

public class Program
{
    public static void Main()
    {
        Console.WriteLine(ConvertToString(5.00m));
        Console.WriteLine(ConvertToString(5.01m));
        Console.WriteLine(ConvertToString(5.99m));
        Console.WriteLine(ConvertToString(5.000000191m));
        Console.WriteLine(ConvertToString(5.000000191000m));
        Console.WriteLine(ConvertToString(51028931298373.000000191000m));
    }

    public static string ConvertToString(decimal value)
    {
        decimal whole = Math.Truncate(value);
        decimal fractional = value - whole;
        return ConvertToString(whole, fractional);
    }

    public static string ConvertToString(decimal whole, decimal fractional)
    {
        if (fractional == 0m)
        {
            return $"{whole:F0}.00";
        }
        else
        {
            string fs = fractional.ToString("F28").Substring(2).TrimEnd('0');
            return $"{whole:F0}.{fs}";
        }
    }
}

Results

5.00
5.01
5.99
5.000000191
5.000000191
51028931298373.000000191
Priapitis answered 19/4, 2023 at 21:36 Comment(0)
W
-2

Use a regex: Regex.Match("\.(?\d+)") Someone correct me if I'm wrong here

Wheen answered 23/10, 2012 at 20:22 Comment(1)
Not very popular with Regex.Match but I've received the following error when trying to get the value of the decimal ArgumentException was unhandled: parsing "\.(?\d+)" - Unrecognized grouping construct.Epoch
S
-2

It is very simple

       float moveWater =  Mathf.PingPong(theTime * speed, 100) * .015f;
       int    m = (int)(moveWater);
       float decimalPart= moveWater -m ;

       Debug.Log(decimalPart);
Spout answered 18/4, 2015 at 14:16 Comment(0)
T
-2

Why not use int y = value.Split('.')[1];?

The Split() function splits the value into separate content and the 1 is outputting the 2nd value after the .

There answered 13/7, 2015 at 19:33 Comment(2)
This will work: Int32.Parse((12.05123d.ToString("0.00").Split('.')[1]))Ayer
Because you are casting it to a string to do string manipulation. I don't think you realize just how slow and wasteful this is.Doyenne

© 2022 - 2024 — McMap. All rights reserved.