2012-05-25 7 views
18

Ich habe Strings, die die Dezimalwerte darstellen, ex: "0,010", "0,0100000" "00,01000"Clojure Dezimalstellen gerundet

ich sie bestimmtes Format runden mag, ab. # ##

in Java haben wir:

public BigDecimal setScale(int newScale, RoundingMode roundingMode) { 
    return setScale(newScale, roundingMode.oldMode); 
} 

Was ist der beste Ansatz, um dies eher in Clojure zu erreichen, als Interop verwenden?

Antwort

26

Sie können Clojures format für diesen Zweck verwenden. Es sollte Ihnen eine Lösung für Ihr Problem bieten. Hier sind einige Beispiele und eine Referenz:

user=> (format "%.2f" 0.010) 
"0.01" 
user=> (format "%.2f" 0.010000) 
"0.01" 
user=> (format "%.2f" 00.010000000) 


user=> (doc format) 
------------------------- 
clojure.core/format 
([fmt & args]) 
    Formats a string using java.lang.String.format, see java.util.Formatter for format 
    string syntax 
+0

cl-Format anstelle von Format verwendet werden soll - Format ist nur eine dünne Hülle um die Java. util.Formatter und deswegen behandelt es zum Beispiel nicht die BigInt von Clojure. Ab Clojure 1.3, wenn Ihre Nummer für eine lange Zeit zu groß ist, wird es in BigInt, der Clojure-Implementierung, überlaufen, anstelle von BigInteger, der Java-Implementierung. Wie Sie vielleicht raten, behandelt java.util.Formatter nicht die Clojure-Implementierung und löst Ausnahme aus. – Unknown

+2

nicht rund, nur Böden es. – celwell

18

Dies ist eine leicht modifizierte Version eines Beispiels bei clojure-doc.org:

(defn round2 
    "Round a double to the given precision (number of significant digits)" 
    [precision d] 
    (let [factor (Math/pow 10 precision)] 
    (/ (Math/round (* d factor)) factor))) 

@ number23_cn Antwort ist die richtige für viele Fälle. Eine echte Rundungsfunktion mit einem Präzisionsargument kann jedoch nützlich sein, wenn Sie z. B. eine Sequenz mit jeder gerundeten Zahl anzeigen möchten. Dann können Sie einfach round2 über die Sequenz Karte jede Zahl auf einmal zu formatieren:

(map (partial round2 2) [0.001 10.123456 9.5556]) 

die zurück

(0.0 10.12 9.56) 

Das ist nützlich für eine längere Sequenz, natürlich.


Eine weitere Option ist cl-format zu verwenden, die format eine Clojure Implementierung von Common Lisp ist ist. Es ist ähnlich wie Clojures format (das auf java.util.Formatter basiert), hat aber eine andere Syntax und erlaubt einige raffiniertere Tricks.

(clojure.pprint/cl-format nil "~,2f" 23.456) 
; => "23.46" 

Die ~{ ~} Richtlinie erlaubt Verarbeitungssequenzen, wie im ersten Beispiel oben:

(clojure.pprint/cl-format nil "~{ ~,2f~}" [0.001 10.123456 9.5556]) 
; => " 0.00 10.12 9.56" 

~{ ~} erwartet eine Sequenz als ein Argument, um zu sehen, und fressen Elemente der Folge einer nach dem anderen unter Verwendung von was auch immer Anweisungen erscheinen zwischen ~{ und ~}.

(Die chapter on format von Peter Seibel Practical Common Lisp zu Common Lisp ist die beste Einführung ist format und damit zu Clojure der cl-format, imo. Die documentation on CL's format in der üblichen Quelle, die Common Lisp Hyperspec, kann schwierig sein, manchmal zu verwenden. Die section on CL's format in Common Lisp The Language ist etwas besser.)

+0

Der Docstring in der Funktion round2 gibt fälschlicherweise an, dass der Genauigkeitsparameter sich auf die Zahl bezieht, wenn es sich um signifikante Ziffern handelt. https://en.wikipedia.org/wiki/Significant_figures sollte es sagen "Anzahl der Nachkommastellen" – antonmos

1

Die angenommene Antwort empfiehlt format, aber format nicht Runde (wie in einem der Kommentare hingewiesen). Die andere Antwort (von Mars) funktioniert nicht für BigDecimal s.Zur Abrundung bigdec s auf eine Anzahl von Dezimalstellen in Clojure die einzige Lösung, die ich gefunden habe, ist Java-Interop zu verwenden:

(defn round [s] 
    (fn [n] 
    (assert (bigdec? n)) 
    (.setScale n s RoundingMode/HALF_EVEN))) 

(def round4 (round 4)) 
Verwandte Themen