2014-03-03 7 views
6

Ich war in der Mitte einige Legacy-Code zu modernisieren, wenn ich in die folgende Zeile gestolpert:Was ist der beste Weg, um eine ungerade Zahl zu einer geraden zu runden?

rounded_val = (len(src_string)/2) * 2

Was es war es tat Vorteil Python's weird integer division nehmen, den Längenwert des Strings abzurunden, wenn ungerade, zum ersten geraden Wert vor ihm. Aber die Integer-Division wird sich in Python 3 ändern, und ich muss diese Zeile ändern. Zuerst dachte ich, dieses:

rounded_val = len(src_string) if len(src_string)%2 == 0 else len(src_string)-1

Aber das nennt len() 3 mal. Dann dachte ich daran, die ursprüngliche Idee zu verwenden, aber mit dem Etagenunterteilungsoperator //, und dachte, es könnte weniger kompatibel sein, um es so zu machen, und dass ich math.floor() stattdessen verwenden sollte (aber dann müsste ich einen anderen Import für math haben).

Ich überlege das wahrscheinlich, aber was ist die optimale Möglichkeit, dies in Python zu tun?

PS: Die Ausgabe muss eine ganze Zahl sein.

+0

Möchten Sie, dass ungerade Zahlen auf- oder abgerundet werden? –

+1

Down, es ist in der Frage. –

+1

Sie wissen, wie sie sagen * vorzeitige Optimierung ist die Wurzel allen Übels? * Der Unterschied zwischen der "langsamen" Funktion in Ihrer Frage und der ausgewählten Antwort ist 0,1 * Mikrosekunden *. Selbst wenn Sie eine Million dieser Berechnungen nacheinander durchgeführt haben, beträgt der Leistungsunterschied lediglich 100 Millisekunden. Die ausgewählte Antwort ist clever, aber wenn Ihre Mitarbeiter Bitmathematik nicht verstehen, verwenden Sie den expliziteren Operator für die Unterteilung in Unterteilungen. P.S. sag nicht "das sieht schneller aus" - beweise es. Python hat speziell dafür ein [timeit] (http://docs.python.org/2/library/timeit.html) Modul. – nemec

Antwort

4

Wie wäre es damit:

rounded_val = len(src_string) & (-2) 

Obwohl es manchmal jemand nicht vertraut mit binären Arithmetik nicht offensichtlich ist.

+1

+1 für die Schreibweise -2, aber AShelly bereits dich zu schlagen. – kojiro

+1

Ja, ich sah AShelly Einreichung nachdem ich meine eingereicht. Er hat mich eine ganze Minute geschlagen. – Vlad

+0

@AShelly hat dich bis zur Pointe geschlagen, aber da deine Antwort weniger Operationen erfordert, werde ich deiner Gemeinschaft wegen der Gemeinschaft als korrekt markieren. –

19

Verwenden // Boden Division statt, wenn Sie nicht wie für Integer-Operanden auf dem Python 2 / Verhalten unter Berufung:

rounded_val = (len(src_string) // 2) * 2 
+1

Das Problem ist nicht, dass ich es nicht mag, ist, dass das Divisionsverhalten in Python 3 ändern wird und diese Zeile brechen würde. –

+3

@LuizBerti: sicher, wenn Sie möchten, dass Ihr Code über Versionen hinweg kompatibel ist, dann ist die Verwendung von '//' anstelle von '/' absolut der Weg zu gehen. –

+1

@LuizBerti: obwohl Bit-Maskierung mit negativen 1 ist auch süß. –

1

Warum dies nicht:

rounded_val = len(src_string) - len(src_string) % 2 
+0

Das ruft immer noch 'len()' zweimal auf. Wahrscheinlich nicht der beste Weg ... –

2

Der // Betreiber wahrscheinlich ist Ihre beste Wette, aber Sie könnten auch die divmod Funktion verwenden:

rounded_val = divmod(len(src_string), 2)[0] * 2 
10

Vielleicht

rounded_val = len(src_string) & ~1 

löscht diese einfach die 1s Bit, das ist genau das, was Sie brauchen. Funktioniert nur für int s, aber len sollte immer ganzzahlig sein.

+0

Ich liebe die Art, wie Sie denken, mein lieber Herr, bitweise Operatoren sind wahrscheinlich schneller als mathematische. Danke vielmals! –

Verwandte Themen