10進数の整数部分を取得するための最良の方法


89

小数の整数部分(c#)を返す最良の方法は何ですか?(これは、intに収まらない可能性のある非常に大きな数に対して機能する必要があります)。

GetIntPart(343564564.4342) >> 343564564
GetIntPart(-323489.32) >> -323489
GetIntPart(324) >> 324

これの目的は次のとおりです。dbの10進数(30,4)フィールドに挿入しており、フィールドに対して長すぎる数値を挿入しようとしないようにしたい。小数の整数部分の長さを決定することは、この操作の一部です。


int部分を取得することはできません。整数部分を取得し、小数部分を捨てることができます。Decimalの整数部分は、intを簡単にオーバーフローさせ、スローまたはラップアラウンドして、コードをサイレントに強制終了する可能性があります。

1
さて、それがこの質問が見た目ほど単純ではない理由です。非常に大きな数でも、小さな数と同じくらい確実に機能するために、これが必要です。ただし、「整数」は「int」よりも正確です。上記で言い換えます。
YaakovEllis

回答:


212

ちなみに、(int)Decimal.MaxValueはオーバーフローします。小数が大きすぎてintボックスに入れることができないため、小数の「int」部分を取得できません。チェックしたばかりです...長い間は大きすぎます(Int64)。

ドットの左側に10進値のビットが必要な場合は、次のようにする必要があります。

Math.Truncate(number)

値を... DECIMALまたはDOUBLEとして返します。

編集:切り捨ては間違いなく正しい機能です!


したがって、結果は小数または倍精度であり、ポイントの後には何もありませんが、結果を「int」(小数点以下の桁数なし)として格納するための組み込みオブジェクトはありません。
Coops 2014年

@CodeBlend:精度を失いたいという願望を中心にフレームワークを設計する必要はあまりありません。

@CodeBlend:数値の小数値を切り落とすため、精度が失われます。何をしているのかわからない。

これが機能するかどうかはわかりません。Math.Truncate(-5.99999999999999999)は-6.0を返すので... !!
バーラトモリ2017

@Bharat Mori:-5.99999999999999999は、切り捨てられる前に-6.0に丸められているようです。接尾辞「m」を付けてみてください。うまくいきます。Math.Truncate(-5.99999999999999999m)は-5を返します。
ヘンリー


4

あなたがしていることに依存します。

例えば:

//bankers' rounding - midpoint goes to nearest even
GetIntPart(2.5) >> 2
GetIntPart(5.5) >> 6
GetIntPart(-6.5) >> -6

または

//arithmetic rounding - midpoint goes away from zero
GetIntPart(2.5) >> 3
GetIntPart(5.5) >> 6
GetIntPart(-6.5) >> -7

デフォルトは常に前者です。これは驚きかもしれませんが、非常に理にかなっています。

明示的なキャストは次のことを行います。

int intPart = (int)343564564.5
// intPart will be 343564564

int intPart = (int)343564565.5
// intPart will be 343564566

あなたが質問を言った方法から、これはあなたが望むものではないように聞こえます-あなたは毎回それを床に置きたいです。

私はします:

Math.Floor(Math.Abs(number));

また、サイズも確認してください。decimalかなり大きくなる可能性があるため、を使用する必要がある場合がありますlong


(long)Decimal.MaxValueがオーバーフローします。

フェアポイント-Math.Truncate(decimal)がdecimalを返すのはそのためだと思います。
キース

C#では、intへのキャストは丸められないため、(int)0.6fは0になり、(int)343564565.5は6ではなく5で終了します。ここで試してください:repl.it/repls/LuxuriousCheerfulDistributeddatabase
sschmidTU

0

あなたはそれをキャストする必要があります:

int intPart = (int)343564564.4342

それでも後の計算で小数として使用する場合は、Math.Truncate(または、負の数に対して特定の動作が必要な場合はMath.Floor)が必要な関数です。


5
これは間違っている間違っている間違っている。結果がInt32が保持できる値よりも大きい場合、例外がスローされるか、(さらに悪いことに!!!)サイレントにオーバーフローしてラップバックし、知らないうちに完全に誤った結果が返されます。

2
いいえ、それは間違いではありません。多くの場合、非常に大きな小数/浮動小数点値には有効ではありませんが、ほとんどの状況では完全に問題ありません。多くの場合、コーディング時に数値が十分に低くなるように制約されるため、これが問題になる必要はありません。また、すべての値で機能するMath.Truncateソリューションを提供しました。
ノルドール2009年

2
なぜあなたが私に腹を立てているのかわかります。事実はあなたの答えが間違っているということです。数が少ないので、壊れないようにチャンスをつかむように彼に言っています。取るのは愚かなリスクです。答えを編集して、Math.Truncate以外のすべてを唯一の正しい部分として削除する必要があります。

1
あなたは彼らがASSUMEについて何を言っているか知っています。また、あなたの仮定は特にひどいです。それは炎症性ですか?私はあなたがそれを言うことができると思います。また、誰かに愚かなことをして、将来的に問題を引き起こすようなことをするように言うことは、非倫理的ではないとしても、炎症を起こすと言うこともできます。

1
確かに、私が誤解を招くような答えをするつもりなら、それは間違っているでしょう。いわば、私はただ助けようとしていました。私が質問を少し誤解したり、完全に理解していなかったりしたことで有罪になった場合、それは十分に公平です-それは犯罪ではありません。では、なぜ今議論しているのでしょうか。私たちは皆、Truncateが正しい答えであることに同意します。
ノルドール2009年

0

値とその小数部分の値を分離する非常に簡単な方法。

double  d = 3.5;
int i = (int)d;
string s = d.ToString();
s = s.Replace(i + ".", "");

sは小数部分= 5であり、
iは整数= 3としての値です。


1
上記のトップアンサーを参照してください。(int)Decimal.MaxValueオーバーフローするため、これは機能しません。
YaakovEllis

0

お役に立てば幸いです。

/// <summary>
/// Get the integer part of any decimal number passed trough a string 
/// </summary>
/// <param name="decimalNumber">String passed</param>
/// <returns>teh integer part , 0 in case of error</returns>
private int GetIntPart(String decimalNumber)
{
    if(!Decimal.TryParse(decimalNumber, NumberStyles.Any , new CultureInfo("en-US"), out decimal dn))
    {
        MessageBox.Show("String " + decimalNumber + " is not in corret format", "GetIntPart", MessageBoxButtons.OK, MessageBoxIcon.Error);
        return default(int);
    } 

    return Convert.ToInt32(Decimal.Truncate(dn));
}

-2
   Public Function getWholeNumber(number As Decimal) As Integer
    Dim round = Math.Round(number, 0)
    If round > number Then
        Return round - 1
    Else
        Return round
    End If
End Function

1
受け入れられた回答(8年以上前に投稿された)は、この回答が間違っている理由を説明しています。の範囲はの範囲decimalよりはるかに大きいですint。また、これはVBの質問ではありません。
ジョーファレル

@ JoeFarrell-答えが間違っていると感じた場合は、その効果にコメントを残すだけでなく、反対票を投じることを検討できます。ただし、フラグを立てないでください(私が言っているわけではありません)。それは質問に答える試みです。言語が間違っているかもしれませんし、VBでも間違っているかもしれませんが、それは試みです。たとえば、「答えが間違った質問に答えた場合、それは答えではありませんか?」を参照してください。
ワイハリー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.