ダブルから小数部分を取得します


83

小数ドットの後の数字を整数で受け取りたいのですが。たとえば、1.05から05のみ、または2.50から50のみ 0.50ではありません


15
2.50はちょうど2.5です。私はあなたが文字列について話していると思います。
ティムシュメルター2012年

3
常に小数点以下2桁を返していますか?入力Aはdecimalfloatstring、...?
グレッグ

3
使用例は、次回のために、質の高い回答を得るのに大いに役立ちます。
tmesser 2012年

はい、2桁のみ、入力は10進数です
user1095549 2012年

3
C#開発チームは、この非常に一般的な操作にMath.DecimalPart(double x)などの単一のMath.functionがないことを恥ずかしく思う(そして行動を起こす)必要があります。私たちの多くが頻繁に行う必要のあることには、「これを試しましたか、それについて考えましたか」という方法が多すぎます。
philologon

回答:


-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]乗数を使用する[10のN乗(例: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/をご覧ください。


ToString()は整数の小数部分を返さないため、注意してください。つまり、MyValueが3の場合、MyValue.ToString()は "3"を返すため、Split( '。')[1]がスローされます。必要な小数点以下の桁数に明示的に形式を指定することを検討してください。MyValue.ToString( "F2")。Split( '。')[1]
Alex Beynenson 2014

7
このソリューションは、このページの他のソリューションよりも約2桁遅く、私自身の回答よりも4桁遅くなっています。
tmesser 2014年

1
このソリューションは文化に固有です。たとえば、ロシア語と英語-米国では、小数点記号が異なります(対応してコンマとドット)。したがって、このコードは他のカルチャ設定では失敗します。
Yury Schkatula 2015年

2
このソリューションは.、で分割されますが、これは必ずしも小数点記号ではありません(つまり、ヨーロッパでは小数点記号はです,)。あなたはCultureInfo.Invariantそれを国際的にするために追加しなければなりません。使用するだけの方が簡単x - Math.Truncate(x)ですが、その結果に魔法をかけますか。
アベル

3
@ Kiquenet7回目の改訂だから。これが元の答えでした:stackoverflow.com/revisions/19374418/1
Manfred Radlwimmer 2017

196

最良の方法の最良は次のとおりです。

var floatNumber = 12.5523;

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

結果はあなたが好きなように変換することができます


10
これは受け入れられた答えであり、数学の質問に対する数学の解決策であり、文字列の操作で面倒なことをする必要はありません
johnc 2014年

19
この解決策には「問題」があると思います。floatNumberが「10.2」の場合、変数xは「0.19999999999999929」のようになります。これが期待どおりに機能したとしても、結果は「2」ではなく「0.2」になります。
Dherik 2014年

4
@Dherik Float値とDouble値には、小数点以下数桁の減算で常に小さなエラーがあります。それらを重要なものと見なすべきではありません。実際にそのような精度が必要な場合は、10進型を使用する必要があります。Decimalに切り替えることができない(または単に切り替えたくない)場合は、何らかの方法で期待される精度を追跡し、比較操作でそれを考慮する必要があります。私は通常小数点以下4桁を使用しますが、例外がある場合もあります。
philologon 2015年

msdn.microsoft.com/en-us/library/から:「一部の数値は小数の2進値として正確に表すことができないため、浮動小数点数は実数にしか近似できません」
philologon

1
最後のコメント:Math.Truncateを使用することは、この種の状況に対するMathライブラリの作成者の意図でした。@Matteraiの答えは受け入れられるべきです。
philologon 2015年

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

これは、あなたの数が小数点以下2桁しかないことを前提としています。


(318.40d % 1) * 100出力39.9999999999977、丸め誤差を回避するためにキャストを使用できます:var decPlaces = (int)(((decimal)number % 1) * 100);
orad 2015

@orad良い呼びかけです-浮動小数点数には常にこれらの小さな不正確さがあります。したがって、一貫した動作を保証するためにキャストすることはかなり賢明です。Matteraiの方が技術的には正しいのですが、答えを更新します。
tmesser 2015

26

'Math.Truncate'アプローチよりもクリーンではるかに高速なソリューションがあります。

double frac = value % 1;

5
注:負の値のために、それが負である:-12.34%1 => -0.33999999999999986
アレックスPOCA

15

丸めの問題のない解決策:

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

出力: 20

10進数にキャストしなかった場合は、を出力することに注意してください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のものに
賛成

私はこれを使用しました... 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
テストしませんでしたが、これはフロートの不正確さに悩まされていますね。
mafu 2015年

10.20それが出力します19。私の答えを見てください。
orad 2015

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桁の10進数を取得することです。数については318.401567d、ソリューションが期待される0.401567場所に出力します40
orad 2015

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の値を2倍にすることを検討してください。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後に2番目の値を出力します。.


これは機能します:Int32.Parse((12.05123d.ToString("0.00").Split('.')[1]))
orad 2015

文字列操作を行うために文字列にキャストしているためです。これがどれほど遅くて無駄であるかをあなたは理解していないと思います。
dmarra 2016
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.