Der beste Weg, um eine ganze Zahl als Teil einer Dezimalzahl zu erhalten


87

Was ist der beste Weg, um den ganzen Zahlenteil einer Dezimalstelle (in c #) zurückzugeben? (Dies muss für sehr große Zahlen funktionieren, die möglicherweise nicht in ein int passen.)

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

Der Zweck davon ist: Ich füge in ein Dezimalfeld (30,4) in der Datenbank ein und möchte sicherstellen, dass ich nicht versuche, eine Zahl einzufügen, die für das Feld zu lang ist. Das Bestimmen der Länge des ganzzahligen Teils der Dezimalstelle ist Teil dieser Operation.


Sie können den int-Teil nicht bekommen; Sie können den ganzen Zahlenteil erhalten und den Bruchteil wegwerfen. Der ganzzahlige Teil einer Dezimalstelle kann leicht ein int überlaufen und entweder werfen oder umwickeln, wodurch Ihr Code stillschweigend beendet wird.

1
Deshalb ist diese Frage nicht so einfach, wie es scheint. Ich brauche dies, um für sehr große Zahlen genauso zuverlässig zu arbeiten wie für kleine Zahlen. "Ganze Zahl" ist jedoch genauer als "int" - ich werde oben umformulieren.
Yaakov Ellis

Antworten:


210

Übrigens, Leute, (int) Decimal.MaxValue wird überlaufen. Sie können den "int" -Teil einer Dezimalstelle nicht erhalten, da die Dezimalstelle zu groß ist, um sie in das int-Feld einzufügen. Nur überprüft ... es ist sogar für eine lange Zeit zu groß (Int64).

Wenn Sie das Bit eines Dezimalwerts links vom Punkt haben möchten, müssen Sie Folgendes tun:

Math.Truncate(number)

und geben Sie den Wert als ... DECIMAL oder DOUBLE zurück.

edit: Abschneiden ist definitiv die richtige Funktion!


Das Ergebnis ist also dezimal oder doppelt, was nach dem Punkt niemals etwas enthält, aber es ist kein Objekt eingebaut, um das Ergebnis als "int" (ohne Dezimalstellen) zu speichern, das etwas lahm erscheint.
Coops

@CodeBlend: Es gibt nicht viel Bedarf, Frameworks zu entwerfen, um die Präzision zu verlieren.

@CodeBlend: Sie würden immer noch an Genauigkeit verlieren, weil Sie die Dezimalwerte einer Zahl abschneiden. Ich bin mir nicht sicher, worauf du hinaus willst.

Ich bin mir nicht sicher, ob dies funktionieren wird oder nicht. Weil Math.Truncate (-5.99999999999999999) für mich -6.0 zurückgibt ... !!
Bharat Mori

@ Bharat Mori: Es scheint, dass -5.99999999999999999 vor dem Abschneiden auf -6.0 gerundet wird. Versuchen Sie es mit dem Suffix "m" und es wird funktionieren. Math.Truncate (-5.99999999999999999m) ergibt -5.
Henry


4

Kommt darauf an, was du tust.

Zum Beispiel:

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

oder

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

Die Standardeinstellung ist immer die erstere, was eine Überraschung sein kann, aber sehr sinnvoll ist .

Ihre explizite Besetzung reicht aus:

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

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

Nach der Art und Weise, wie Sie die Frage formuliert haben, klingt es so, als ob dies nicht das ist, was Sie wollen - Sie möchten es jedes Mal auf den Boden legen.

Ich würde tun:

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

Überprüfen Sie auch die Größe Ihrer decimal- sie können ziemlich groß sein, so dass Sie möglicherweise eine verwenden müssen long.


(lang) Decimal.MaxValue läuft über.

Fairer Punkt - Ich denke, deshalb gibt Math.Truncate (dezimal) dezimal zurück.
Keith

In C # wird das Casting in int nicht gerundet, sodass (int) 0.6f 0 ist und (int) 343564565.5 mit 5 und nicht mit 6 endet
sschmidTU

0

Sie müssen es nur als solches besetzen:

int intPart = (int)343564564.4342

Wenn Sie es in späteren Berechnungen weiterhin als Dezimalzahl verwenden möchten, ist Math.Truncate (oder möglicherweise Math.Floor, wenn Sie ein bestimmtes Verhalten für negative Zahlen wünschen) die gewünschte Funktion.


5
Das ist falsch falsch falsch. Wenn das Ergebnis größer ist als das, was ein Int32 halten kann, wird es entweder eine Ausnahme auslösen oder (noch schlimmer !!!) lautlos überlaufen und sich wieder umwickeln, was zu einem völlig falschen Ergebnis führt, ohne dass Sie davon etwas wissen.

2
Nein, das ist nicht falsch . Es ist oft nicht gültig für sehr große Dezimalstellen / Gleitkommawerte, aber es ist für die meisten Situationen vollkommen in Ordnung. Die Anzahl der Zahlen muss beim Codieren sehr niedrig sein, sodass dies kein Problem darstellen muss. Außerdem habe ich eine Math.Truncate-Lösung bereitgestellt, die für alle Werte funktioniert.
Noldorin

2
Ich verstehe, warum du sauer auf mich bist. Tatsache ist, dass Ihre Antwort falsch ist. Du sagst ihm, er soll das Risiko eingehen, dass es nicht kaputt geht, weil viele Zahlen klein sind. Es ist ein dummes Risiko. Sie sollten Ihre Antwort bearbeiten und alles außer Math.Truncate als einzig richtigen Teil entfernen.

1
Sie wissen, was sie über ASSUME sagen. Auch Ihre Annahme ist besonders schrecklich. Ist das entzündlich? Das könnte man wohl sagen. Sie können auch sagen, dass es auch entzündlich ist, jemandem zu sagen, er solle etwas Dummes tun, das ihm später Probleme bereiten wird, wenn nicht sogar unethisch.

1
Das wäre in der Tat falsch, wenn ich eine irreführende Antwort geben wollte. Ich habe einfach versucht zu helfen. Wenn ich mich eines leichten Missverständnisses schuldig mache oder die Frage nicht vollständig schätze, ist das fair genug - es ist kein Verbrechen. Warum streiten wir uns jetzt? Wir sind uns alle einig, dass Abschneiden die richtige Antwort ist.
Noldorin

0

Sehr einfache Möglichkeit, den Wert und seinen Bruchteilwert zu trennen.

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

s ist Bruchteil = 5 und
i ist Wert als ganze Zahl = 3


1
Siehe die obere Antwort oben. Dies funktioniert nicht, da (int)Decimal.MaxValuees überlaufen wird.
Yaakov Ellis

0

Ich hoffe dir zu helfen.

/// <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
Die akzeptierte Antwort, die vor mehr als acht Jahren veröffentlicht wurde, erklärt, warum diese Antwort falsch ist. Die Reichweite von decimalist weitaus größer als die von int. Auch dies ist keine VB-Frage.
Joe Farrell

@JoeFarrell - Wenn Sie der Meinung sind, dass die Antwort falsch ist, können Sie sie auch ablehnen, indem Sie nur einen Kommentar zum Effekt hinterlassen. Kennzeichnen Sie es jedoch nicht (nicht, dass ich sage, dass Sie es haben). Es ist ein Versuch , die Frage zu beantworten. Es kann in der falschen Sprache sein, es kann sogar in VB falsch sein, aber es ist ein Versuch. Siehe zum Beispiel " Wenn eine Antwort die falsche Frage beantwortet, ist es keine Antwort? ".
Wai Ha Lee
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.