Ursprünglich veröffentlicht im Blog von Takeshi Yu.
Genaue numerische Berechnungen sind in Unternehmensanwendungen von größter Bedeutung, insbesondere wenn es um Finanzen, Buchhaltung oder Inventar geht. Selbst geringfügige Rundungsfehler können zu erheblichen Problemen führen. Die verbesserte BCMath Object API von PHP 8.4 bietet eine verfeinerte Lösung für präzise und effiziente Dezimalberechnungen.
Erfahrene PHP-Entwickler sind mit der Ungenauigkeit von Gleitkommazahlen vertraut:
$a = 0.1; $b = 0.2; var_dump($a + $b); // Outputs: 0.30000000000000004
Diese Ungenauigkeit ist im finanziellen Kontext inakzeptabel. Diese kleinen Fehler häufen sich und führen zu Abweichungen in der realen Welt.
Präzise Dezimalrechnungen beginnen mit der Datenbank. Wesentlich ist der Typ DECIMAL
:
// In Laravel Migration Schema::create('items', function (Blueprint $table) { $table->id(); $table->decimal('quantity', 10, 3); // Precision: 10 digits, 3 decimal places $table->decimal('price', 10, 3); // Precision: 10 digits, 3 decimal places $table->decimal('discount', 10, 3); // Precision: 10 digits, 3 decimal places $table->decimal('tax', 10, 3); // Precision: 10 digits, 3 decimal places // ... other columns });
DECIMAL
stellt sicher:
Obwohl möglicherweise etwas langsamer als FLOAT
, überwiegt der Präzisionsvorteil den Leistungsunterschied in geschäftskritischen Systemen.
Laravel vereinfacht die Dezimalverarbeitung mit seinem Casting-System:
class Item extends Model { protected $casts = [ 'quantity' => 'decimal:3', 'price' => 'decimal:3', 'discount' => 'decimal:3', 'tax' => 'decimal:3', ]; }
Denken Sie jedoch daran, dass das Laravel-Casting in erster Linie Folgendes schafft:
Selbst bei korrekten Datenbanktypen und Laravel-Casting können Berechnungsfehler auftreten:
// Database values $item1 = Item::find(1); // price: "99.99" $item2 = Item::find(2); // price: "149.99" // Calculation without BCMath $subtotal = $item1->price + $item2->price; $tax = $subtotal * 0.05; // 5% tax var_dump($tax); // Outputs: float(12.499000000000002) instead of 12.499
Dies geschieht, weil PHP während der Arithmetik implizit Zeichenfolgen in Zahlen umwandelt:
// String values from database $price1 = "99.99"; $price2 = "149.99"; echo gettype($price1); // string // Implicit conversion to float $total = $price1 + $price2; echo gettype($total); // double (float)
Die traditionelle BCMath-Erweiterung bietet Präzision:
// Database values $item1 = Item::find(1); // price: "99.99" $item2 = Item::find(2); // price: "149.99" // Using BCMath functions $subtotal = bcadd($item1->price, $item2->price, 3); $tax = bcmul($subtotal, $item2->tax, 3); var_dump($tax); // Precisely outputs: string(5) "12.499"
Komplexe Berechnungen werden jedoch ausführlicher und weniger wartbar:
// Complex order calculation (using BCMath functions) // ... (code omitted for brevity)
Die objektorientierte BCMath-API von PHP 8.4 vereinfacht präzise Berechnungen:
use BCMath\Number; $item1 = Item::find(1); $price = new Number($item1->price); $quantity = new Number($item1->quantity); $discountRate = new Number($item1->discount); $taxRate = new Number($item1->tax); // Natural and readable calculations $subtotal = $price * $quantity; $discount = $subtotal * $discountRate; $afterDiscount = $subtotal - $discount; $tax = $afterDiscount * $taxRate; $total = $afterDiscount + $tax; var_dump($total); // Automatically converts to string
Vorteile der neuen API:
Stringable
Schnittstellenimplementierung.Weitere Eleganz wird mit den Accessoires von Laravel erreicht:
use BCMath\Number; class Item extends Model { // ... (accessor methods for quantity, price, discount, tax using Number) ... }
Oder mit einer individuellen Besetzung:
// ... (DecimalCast class implementation) ...
Dann:
$item1 = Item::find(1); $subtotal = $item1->price * $item1->quantity; // ... (rest of the calculation) ...
Bei der Bestandsverwaltung im Gesundheitswesen sind präzise Dezimalberechnungen von entscheidender Bedeutung. Die in Laravel integrierte BCMath Object API von PHP 8.4 verbessert die Handhabung dieser Berechnungen erheblich und bietet Präzision, Lesbarkeit, Wartbarkeit und Typsicherheit. Während die älteren BCMath-Funktionen ihren Zweck erfüllten, rationalisiert dieser neue Ansatz die Entwicklung erheblich.
Das obige ist der detaillierte Inhalt vonUmgang mit Dezimalrechnungen in PHP mit der neuen BCMath-Objekt-API. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!