从双精度数中获取小数部分


83

我想以整数形式接收小数点后的数字。例如,从1.05开始只有05或从2.50开始只有05,而不是0.50


15
2.50只是2.5。我以为你在说弦。
蒂姆·施密特

3
您是否总是返回小数点后的前两位数字?是输入decimalfloatstring,...?
格雷格2012年

3
用法示例在下一次获得高质量答案方面大有帮助。
tmesser 2012年

是的,只有两个数字,输入为十进制
user1095549 2012年

3
C#开发团队应该为这个非常常见的操作没有Math.DecimalPart(double x)之类的单个Math.function而感到尴尬(并采取行动)。对于我们许多人经常需要做的事情,有太多“您尝试过,您是否考虑过”的方法。
philologon

Answers:


-20

更新的答案

在这里,我给出了3种方法。

[1]使用Math.Truncate的数学解决方案

 var float_number = 12.345;
 var result = float_number - Math.Truncate(float_number);

//输入:1.05
//输出:“ 0.050000000000000044”

//输入:10.2
//输出:0.19999999999999929

如果这不是您期望的结果,则必须将结果更改为所需的形式(但是您可能会再次进行一些字符串操作。)

[2]使用乘数[是N的幂的10(例如10²或10³),其中N是小数位数]

       // multiplier is " 10 to the power of 'N'" where 'N' is the number 
       // of decimal places
       int multiplier = 1000;  
       double double_value = 12.345;
       int double_result = (int)((double_value - (int)double_value) * multiplier);

//输出345

如果小数位数不固定,则此方法可能会产生问题。

[3]使用“正则表达式(REGEX)”

在使用字符串编写解决方案时,我们应该非常小心。除某些情况外,这是不可取的

如果您要使用小数位进行一些字符串操作,那么这将是更好的选择

    string input_decimal_number = "1.50";
    var regex = new System.Text.RegularExpressions.Regex("(?<=[\\.])[0-9]+");
    if (regex.IsMatch(input_decimal_number))
    {
        string decimal_places = regex.Match(input_decimal_number).Value;
    }

//输入:“ 1.05”
//输出:“ 05”

//输入:“ 2.50”
//输出:“ 50”

//输入:“ 0.0550”
//输出:“ 0550”

您可以在http://www.regexr.com/上找到有关Regex的更多信息


注意ToString(),因为它不会返回整数的小数部分,也就是说,如果MyValue为3,则MyValue.ToString()将返回“ 3”,因此Split('。')[1]将抛出。考虑明确地将格式指定为所需的小数位数:MyValue.ToString(“ F2”)。Split('。')[1]
Alex Beynenson 2014年

7
该解决方案比此页面上的任何其他解决方案慢大约两个数量级,并且比我自己的答案慢四个数量级。
tmesser 2014年

1
该解决方案是特定于文化的。例如,在俄语和英语-美国,有不同的小数点分隔符(对应于逗号和点)。因此,此代码在其他区域性设置下将失败。
Yury Schkatula

2
此解决方案在上拆分.,该并不总是十进制分隔符(即在欧洲,十进制分隔符为,)。您必须添加CultureInfo.Invariant使其国际化。尽管使用起来更容易x - Math.Truncate(x),但您会对结果感到惊讶。
亚伯

3
@Kiquenet,因为这是第七次修订。这是原始答案:stackoverflow.com/revisions/19374418/1
Manfred Radlwimmer

196

最好的最好方法是:

var floatNumber = 12.5523;

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

结果你可以随意转换


10
这应该是公认的答案,是数学问题的数学解决方案,而不会在字符串处理中带来所有繁琐的沉思
johnc

19
我认为此解决方案有一个“问题”。如果floatNumber为“ 10.2”,则变量x类似于“ 0.19999999999999929”。即使这按预期工作,结果也将是“ 0.2”而不是“ 2”。
Dherik 2014年

4
@Dherik的Float和Double值在小数点后几位的减法中始终会出现小错误。您不应该认为这些意义重大。如果您确实需要这种精度,则应使用Decimal类型。如果您不能切换到十进制(或者只是不想),那么您应该以某种方式跟踪期望的精度,并在比较操作中对此加以考虑。我通常使用4个小数位,但可能会有例外。
philologon 2015年

来自msdn.microsoft.com/zh-cn/library/…:“因为某些数字无法精确表示为分数二进制值,所以浮点数只能近似为实数”
philologon

1
最后评论:使用Math.Truncate是Math库作者针对这种情况的意图。@Matterai的答案应该是被接受的。
philologon

80
var decPlaces = (int)(((decimal)number % 1) * 100);

假设您的电话号码只有两位小数。


(318.40d % 1) * 100输出39.9999999999977,可以使用强制转换来解决舍入误差:var decPlaces = (int)(((decimal)number % 1) * 100);
orad

@orad不错的选择-浮点数总是有这些小错误,因此,为确保行为一致,应谨慎选择。我会更新我的答案,尽管Matterai的在技术上仍然更正确。
tmesser

26

有一个比“ Math.Truncate”方法更清洁,更快捷的解决方案:

double frac = value % 1;

5
注意:对于负值,它为负:-12.34%1 => -0.33999999999999986
Alex

15

没有舍入问题的解决方案:

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

输出: 20

请注意,如果我们不将其转换为小数,它将输出19

也:

  • 用于318.40输出:(40而不是39
  • 用于47.612345输出:(61而不是612345
  • 用于3.01输出:(01而不是1

如果您使用的是财务编号,例如,在这种情况下,如果您尝试获取交易金额中的美分,请始终使用decimal数据类型。

更新:

如果将其作为字符串处理(基于@SearchForKnowledge的答案),以下内容也将起作用。

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

然后,您可以使用Int32.Parse将其转换为int。


1
竖起大拇指的mod
伊万德罗·乔(Ivandro Jao)

我使用了... 10.2d.ToString(“ 0.00”,CultureInfo.InvariantCulture).Split('。')[1]
Ziggler,

10

更好的方法 -

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

输出-

56

2
没有测试,但是这会遇到浮动错误,不是吗?
马夫

因为10.20它将输出19。看我的答案。
orad

10

最简单的变体可能是Math.truncate()

double value = 1.761
double decPart = value - Math.truncate(value)

2

我猜这个线程越来越老了,但我不敢相信没有人提到Math.Floor

//will always be .02 cents
(10.02m - System.Math.Floor(10.02m))

对于超级懒惰:double fract(double x) { return x - System.Math.Floor(x); }
费利佩·古铁雷斯

1
var result = number.ToString().Split(System.Globalization.NumberDecimalSeparator)[2]

将其作为字符串返回(但您始终可以将其强制转换为int),并假定数字确实具有“。”。某处。


1
int last2digits = num - (int) ((double) (num /  100) * 100);

问题是要获得前2个十进制数字。对于数字318.401567d解决方案输出0.401567,其中40的预期。
orad

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

0

这是我为类似情况编写的扩展方法。我的应用程序将接收格式为2.3或3.11的数字,其中数字的整数部分表示年份,而小数部分表示月份。

// Sample Usage
int years, months;
double test1 = 2.11;
test1.Split(out years, out months);
// years = 2 and months = 11

public static class DoubleExtensions
{
    public static void Split(this double number, out int years, out int months)
    {
        years = Convert.ToInt32(Math.Truncate(number));

        double tempMonths = Math.Round(number - years, 2);
        while ((tempMonths - Math.Floor(tempMonths)) > 0 && tempMonths != 0) tempMonths *= 10;
        months = Convert.ToInt32(tempMonths);
    }
}

0

那可能是开销,但应该可以。

double yourDouble = 1.05;
string stringForm = yourDouble.ToString();
int dotPosition = stringForm.IndexOf(".");
decimal decimalPart = Decimal.Parse("0" + stringForm.Substring(dotPosition));

Console.WriteLine(decimalPart); // 0.05

0
 string input = "0.55";
    var regex1 = new System.Text.RegularExpressions.Regex("(?<=[\\.])[0-9]+");
    if (regex1.IsMatch(input))
    {
        string dp= regex1.Match(input ).Value;
    }

1
如果您可以添加关于正则表达式如何帮助解决问题的说明,那将非常棒
Cleptus

-1

您可以.从将双精度Remove()转换为字符串后使用该函数获取小数的双精度点中删除点,以便可以执行所需的操作

考虑_Double值为的双精度值0.66781,下面的代码将只显示点后的数字.,即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) 

另一种解决方案

您也可以使用Path以跨平台方式对字符串实例执行操作的类

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

-2

使用正则表达式:Regex.Match("\.(?\d+)")如果我在这里错了,请有人纠正我


并不太受欢迎,Regex.Match但尝试获取小数点的值时收到以下错误ArgumentException was unhandled: parsing "\.(?\d+)" - Unrecognized grouping construct.
Picrofo Software 2012年

-2

很简单

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

       Debug.Log(decimalPart);

-2

为什么不使用int y = value.Split('.')[1];

Split()函数将值拆分为单独的内容,并且1.


这将起作用:Int32.Parse((12.05123d.ToString("0.00").Split('.')[1]))
orad

因为您将其强制转换为字符串以进行字符串操作。我认为您没有意识到这是多么缓慢和浪费。
dmarra
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.