OK - es ist mir fast peinlich, dies hier zu posten (und ich werde es löschen, wenn jemand zum Schließen stimmt), da es wie eine grundlegende Frage erscheint.
Ist dies der richtige Weg, um in C ++ auf ein Vielfaches einer Zahl aufzurunden?
Ich weiß, dass es andere Fragen dazu gibt, aber ich bin besonders daran interessiert zu wissen, wie dies in C ++ am besten funktioniert:
int roundUp(int numToRound, int multiple)
{
if(multiple == 0)
{
return numToRound;
}
int roundDown = ( (int) (numToRound) / multiple) * multiple;
int roundUp = roundDown + multiple;
int roundCalc = roundUp;
return (roundCalc);
}
Update: Entschuldigung, ich habe die Absicht wahrscheinlich nicht klargestellt. Hier sind einige Beispiele:
roundUp(7, 100)
//return 100
roundUp(117, 100)
//return 200
roundUp(477, 100)
//return 500
roundUp(1077, 100)
//return 1100
roundUp(52, 20)
//return 60
roundUp(74, 30)
//return 90
int
.Antworten:
Dies funktioniert für positive Zahlen, nicht sicher über negative. Es wird nur ganzzahlige Mathematik verwendet.
Bearbeiten: Hier ist eine Version, die mit negativen Zahlen arbeitet, wenn Sie mit "up" ein Ergebnis meinen, das immer> = die Eingabe ist.
quelle
if(number<0){ multiple = multiple*(-1); }
zu Beginn hinzu, um negative Zahlen in die richtige Richtung zu rundenif(number<0) multiple = -multiple
ist einfacher.if (remainder == 0)
Test sollte sich um diesen Fall kümmern. Es funktioniert für mich: ideone.com/Waol7BOhne Bedingungen:
Dies funktioniert wie das Abrunden von Null für negative Zahlen
EDIT: Version, die auch für negative Zahlen funktioniert
Tests
Wenn
multiple
ist eine Potenz von 2 (schneller in ~ 3,7 mal http://quick-bench.com/sgPEZV9AUDqtx2uujRSa3-eTE80 )Tests
quelle
& ~(x - 1)
dasselbe ist wie& -x
für die Zweierkomplementarithmetik.Dies funktioniert, wenn der Faktor immer positiv ist:
Bearbeiten: Dies kehrt zurück
round_up(0,100)=100
. In Pauls Kommentar unten finden Sie eine Lösung, die zurückkehrtround_up(0,100)=0
.quelle
num + factor - 1 - (num + factor - 1) % factor
?num - 1 - (num - 1) % factor + factor
führt die gleiche Berechnung ohne das Risiko eines ganzzahligen Überlaufs durch.Dies ist eine Verallgemeinerung des Problems "Wie finde ich heraus, wie viele Bytes n Bits benötigt werden?" (A: (n Bits + 7) / 8).
quelle
(x = roundTo - 1; return (n+x)&~roundTo;)
wie in meiner Antwort sein0xFFF...000
nicht0xFFF7FFF
oder so sein, also möchten Sie entweder die Komplementnegation (-
: minus) von 2 mit einer Potenz von 2 oder einen Bit-Flip auf eine weniger als eine Potenz von 2 (das Komplement invers~
: Tilde) nicht minus). Also(n+x) & ~x
oder(n-roundTo+1) & -roundTo
.Und Sie müssen nicht mit den Bedingungen herumspielen
quelle
Für alle, die eine kurze und süße Antwort suchen. Das habe ich benutzt. Keine Berücksichtigung von Negativen.
Das gibt den vorherigen Faktor zurück.
Ich werde am nächsten zurückkehren. Hoffe das hilft jemandem. :) :)
quelle
Dies funktioniert für jede Float-Nummer oder Basis (z. B. können Sie -4 auf 6,75 runden). Im Wesentlichen wird in einen festen Punkt konvertiert, dort gerundet und dann zurück konvertiert. Es behandelt Negative, indem es AWAY von 0 rundet. Es behandelt auch eine negative Runde auf Wert, indem die Funktion im Wesentlichen in roundDown umgewandelt wird.
Eine int-spezifische Version sieht folgendermaßen aus:
Das ist mehr oder weniger die Antwort von Sockel mit der zusätzlichen Unterstützung für negative Eingaben.
quelle
double round(double value, double multiple) { double sign = value; multiple = std::copysign(multiple, 1.0); value = std::copysign(value, 1.0); return std::copysign(multiple * std::ceil(value / multiple), sign); }
Oder tauschen Sie die Decke gegen eine runde, um eine Rundung zu erhalten.Dies ist der moderne c ++ - Ansatz, der eine Vorlagenfunktion verwendet, die für float, double, long, int und short funktioniert (jedoch nicht für long long und long double aufgrund der verwendeten double-Werte).
Sie können jedoch problemlos Unterstützung für
long long
undlong double
mit Vorlagenspezialisierung hinzufügen, wie unten gezeigt:Um Funktionen zum Aufrunden zu erstellen, verwenden Sie
std::ceil
und um die Verwendung immer abzurundenstd::floor
. Mein Beispiel von oben ist das Runden mitstd::round
.Erstellen Sie die Vorlagenfunktion "Aufrunden" oder besser bekannt als "Runde Decke" wie unten gezeigt:
Erstellen Sie die Vorlagenfunktion "Abrunden" oder besser bekannt als "Abgerundeter Boden" wie unten gezeigt:
quelle
long long
undlong double
. Das gleiche muss natürlich für die beiden anderen Funktionen gemacht werden.Zunächst einmal sollte Ihre Fehlerbedingung (multiple == 0) wahrscheinlich einen Rückgabewert haben. Was? Ich weiß es nicht. Vielleicht möchten Sie eine Ausnahme auslösen, das liegt bei Ihnen. Aber nichts zurückzugeben ist gefährlich.
Zweitens sollten Sie überprüfen, ob numToRound noch kein Vielfaches ist. Andernfalls , wenn Sie hinzufügen
multiple
zuroundDown
, haben Sie die falsche Antwort bekommen.Drittens sind Ihre Darsteller falsch. Du hast gegossen
numToRound
in eine Ganzzahl umgewandelt, aber es ist bereits eine Ganzzahl. Sie müssen vor der Division auf Double und nach der Multiplikation auf Int zurücksetzen.Was möchten Sie zum Schluss für negative Zahlen? Aufrunden "aufrunden" kann auf Null runden (in die gleiche Richtung wie positive Zahlen runden) oder von Null weg (eine "größere" negative Zahl). Oder vielleicht ist es dir egal.
Hier ist eine Version mit den ersten drei Korrekturen, aber ich beschäftige mich nicht mit dem negativen Problem:
quelle
int / int
dies ein int zurückgeben würde, was wir nicht wollten.Runde zur Zweierpotenz:
Nur für den Fall, dass jemand eine Lösung für positive Zahlen benötigt, die auf das nächste Vielfache einer Zweierpotenz gerundet sind (denn so bin ich hier gelandet):
Die eingegebene Nummer bleibt gleich, wenn es sich bereits um ein Vielfaches handelt.
Hier ist die x86_64-Ausgabe, die GCC mit
-O2
oder gibt-Os
(9Sep2013 Build - godbolt GCC online):Jede C-Codezeile entspricht perfekt der Zeile in der Assembly: http://goo.gl/DZigfX
Jede dieser Anweisungen ist extrem schnell , daher ist die Funktion auch extrem schnell. Da der Code so klein und schnell ist, kann er für
inline
die Funktion bei der Verwendung hilfreich sein .Anerkennung:
quelle
Ich benutze:
und für Zweierkräfte:
Beachten Sie, dass beide negativen Werte gegen Null runden (dh für alle Werte auf unendlich runden). Keiner von beiden basiert auf einem vorzeichenbehafteten Überlauf (der in C / C ++ undefiniert ist).
Das gibt:
quelle
n_Align_Up_POT
, seit ich sie in Delphis TList-Klasse gesehen habe. Es hat seine Einschränkungen, wie die Ausrichtung (mehrfach) eine Potenz von 2 ist, aber das ist selten ein Problem, da ich es meistens benutze, um die richtige Ausrichtung für SMID zu erhalten / zu überprüfen. Es ist großartig und es scheint, dass nicht viele Leute davon wissen.Wahrscheinlich sicherer in Floats umzuwandeln und Ceil () zu verwenden - es sei denn, Sie wissen, dass die Int-Division das richtige Ergebnis liefert.
quelle
C ++ rundet jede Zahl ab. Wenn Sie also 0,5 hinzufügen (wenn es 1,5 ist, ist es 2), aber 1,49 ist 1,99, also 1.
BEARBEITEN - Entschuldigung, Sie haben nicht gesehen, dass Sie aufrunden möchten. Ich würde vorschlagen, anstelle von +0.5 eine Ceil () -Methode zu verwenden
quelle
Zum einen, da ich nicht wirklich verstehe, was Sie tun wollen, die Zeilen
könnte definitiv verkürzt werden
quelle
Vielleicht kann dies helfen:
quelle
Immer abrunden
alwaysRoundUp (1, 10) -> 10
alwaysRoundUp (5, 10) -> 10
alwaysRoundUp (10, 10) -> 10
Immer abrunden
alwaysRoundDown (1, 10) -> 0
alwaysRoundDown (5, 10) -> 0
alwaysRoundDown (10, 10) -> 10
Den normalen Weg abrunden
normalRound (1, 10) -> 0
normalRound (5, 10) -> 10
normalRound (10, 10) -> 10
quelle
Auf das nächste Vielfache runden, das zufällig eine Potenz von 2 ist
Dies kann nützlich sein, wenn Sie entlang von Junggesellen zuordnen, bei denen das gewünschte Rundungsinkrement eine Zweierpotenz ist, der resultierende Wert jedoch nur ein Vielfaches davon sein muss. Auf
gcc
dem Körper dieser Funktion werden 8 Montageanweisungen ohne Unterteilung oder Verzweigungen generiert.quelle
Ich habe einen Algorithmus gefunden, der dem oben beschriebenen etwas ähnlich ist:
int [(| x | + n-1) / n] * [(nx) / | x |], wobei x ein Benutzereingabewert und n das verwendete Vielfache ist.
Es funktioniert für alle Werte x, wobei x eine ganze Zahl ist (positiv oder negativ, einschließlich Null). Ich habe es speziell für ein C ++ - Programm geschrieben, aber dies kann grundsätzlich in jeder Sprache implementiert werden.
quelle
Für negative numToRound:
Es sollte wirklich einfach sein, dies zu tun, aber der Standard-Modulo% -Operator verarbeitet negative Zahlen nicht wie erwartet. Zum Beispiel -14% 12 = -2 und nicht 10. Als erstes müssen Sie einen Modulo-Operator erhalten, der niemals negative Zahlen zurückgibt. Dann ist roundUp wirklich einfach.
quelle
Das würde ich tun:
Der Code ist möglicherweise nicht optimal, aber ich bevorzuge sauberen Code gegenüber trockener Leistung.
quelle
int
tofloat
verliert leicht an Präzision und führt zu falschen Antworten.obwohl:
würde vorschlagen, stattdessen vorzeichenlose Ganzzahlen zu verwenden, die das Überlaufverhalten definiert haben.
Sie erhalten eine Ausnahme von multiplen == 0, aber in diesem Fall ist dies ohnehin kein genau definiertes Problem.
quelle
c:
und für dein ~ / .bashrc:
quelle
Ich verwende eine Kombination von Modulen, um die Addition des Restes aufzuheben, wenn
x
es sich bereits um ein Vielfaches handelt:Wir finden die Umkehrung des Rest-dann-Moduls, die mit dem Divisor erneut aufgehoben wird, wenn es sich um den Divisor selbst handelt, und fügen dann hinzu
x
.quelle
Hier ist meine Lösung basierend auf dem Vorschlag des OP und den Beispielen aller anderen. Da fast jeder danach suchte, negative Zahlen zu verarbeiten, macht diese Lösung genau das, ohne die Verwendung spezieller Funktionen, dh abs und dergleichen.
Wenn Sie den Modul vermeiden und stattdessen die Division verwenden, ist die negative Zahl ein natürliches Ergebnis, obwohl sie abgerundet ist. Nachdem die abgerundete Version berechnet wurde, führt sie die erforderliche Berechnung durch, um entweder in negativer oder positiver Richtung aufzurunden.
Beachten Sie auch, dass keine speziellen Funktionen zum Berechnen verwendet werden, sodass dort ein kleiner Geschwindigkeitsschub erfolgt.
quelle
RoundUp(INT_MIN, -1)
alsn / multiple
istint
Überlauf.Ich denke, das sollte dir helfen. Ich habe das folgende Programm in C geschrieben.
quelle
quelle
Dadurch erhalten Sie die gewünschten Ergebnisse für positive Ganzzahlen:
Und hier sind die Ausgaben:
quelle
Dies funktioniert bei mir, hat aber nicht versucht, mit Negativen umzugehen
quelle
Hier ist eine super einfache Lösung, um das Konzept der Eleganz zu zeigen. Es ist im Grunde für Grid-Snaps.
(Pseudocode)
quelle