Korrektes Handling von Geldbeträgen (JSON-RPC): Unterschied zwischen den Versionen

Aus Bitcoin Wiki
Wechseln zu: Navigation, Suche
(Die Seite wurde neu angelegt: „== Überblick == Der Original-Bitcoin-Client speichert alle Bitcoin-Beträge als 64-Bit-Ganzzahlen (Integers), wobei 1 BTC als 100.000.000 (einhundert Millione…“)
 
(kein Unterschied)

Aktuelle Version vom 23. Dezember 2012, 19:15 Uhr

Überblick

Der Original-Bitcoin-Client speichert alle Bitcoin-Beträge als 64-Bit-Ganzzahlen (Integers), wobei 1 BTC als 100.000.000 (einhundert Millionen Satoshis) verarbeitet wird. In der JSON-API werden Beträge hingehen als Gleitkommazahlen mit doppelter Präzision dargestellt, also 1 BTC als 1.00000000.

Wenn du Software schreibst, die das JSON-RPC-Interface verwendet, musst du auf mögliche Gleitkommafehler achten. Du, oder die JSON-Library, die du verwendest, sollte die Beträge entweder zu einer Fixkommadarstellung (mit 8 Nachkommastellen) oder zu einer Ganzzahldarstellung konvertieren. In beiden Fällen muss gerundet werden.

Falsches Handling kann zu problematischen Fehlern führen; wenn du z.B. Nachkommastellen abschneidest, anstatt zu runden, könnten 0.1 BTC als "0.09999999 BTC" angezeigt werden (oder schlimmer, "0.09 BTC").

Der Original-Bitcoin-Client führt eine korrekte Rundung für alle Werte, die er über das RPC-Interface enthält, durch. Das heißt, dass wenn der Wert 0.1 durch deine JSON-RPC-Library zum Wert "0.099999999999" konvertiert wird, dass dieser Wert wieder zu den nächsten 0.00000001 Bitcoins gerundet und daher korrekt als 0.1 BTC behandelt wird.

Der Rest der Seite enthält Beispielcode für verschiedene JSON-Libraries und Programmiersprachen.

BASH

 function JSONtoAmount() {
     printf '%.8f' "$1" | tr -d '.'
 }

C/C++

C/C++ JSON-Libraries geben die JavaScript-Zahl als Typ "double" zurück. Um von einem "double" auf einen 64-Bit-Integer zu konvertieren, multipliziere mit 100.000.000 und runde auf die nächste ganze Zahl:

int64_t JSONtoAmount(double value) {
    return (int64_t)(value * 1e8 + (value < 0.0 ? -.5 : .5));
}

Um auf einen JSON-Wert zu konvertieren, dividiere durch 100.000.000,0 und stelle sicher, dass deine JSON-Implementation "doubles" mit mindestens 8 Stellen nach dem Komma ausgibt:

 double forJSON = (double)amount / 1e8;

ECMAScript

function JSONtoAmount(value) {
    return Math.round(1e8 * value);
}

Perl

sub JSONtoAmount {
    return sprintf '%.0f', 1e8 * shift;
}

PHP

function JSONtoAmount($value) {
    return round($value * 1e8);
}

Python

def JSONtoAmount(value):
    return long(round(value * 1e8))
def AmountToJSON(amount):
    return float(amount / 1e8)

Common Lisp

 (defun json-to-amount (n)
   (coerce (round (* n 1e8)) 'integer))

Vorsicht: Die CL-JSON-Library behandelt Zahlen standardmäßig als Gleitkommazahlen mit einfacher Präzision. Mit dem folgenden Codestück kannst du stattdessen Zahlen mit doppelter Präzision verwenden:

  (set-custom-vars :real (lambda (n)
                            (json::parse-number (concatenate 'string n "d0"))))

Hinweis

Dieser Artikel wurde aus dem Englischen] übersetzt.