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:
<code class="language-php">$a = 0.1; $b = 0.2; var_dump($a + $b); // Outputs: 0.30000000000000004</code>
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
:
<code class="language-php">// 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 });</code>
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:
<code class="language-php">class Item extends Model { protected $casts = [ 'quantity' => 'decimal:3', 'price' => 'decimal:3', 'discount' => 'decimal:3', 'tax' => 'decimal:3', ]; }</code>
Denken Sie jedoch daran, dass das Laravel-Casting in erster Linie Folgendes schafft:
Selbst bei korrekten Datenbanktypen und Laravel-Casting können Berechnungsfehler auftreten:
<code class="language-php">// 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</code>
Dies geschieht, weil PHP während der Arithmetik implizit Zeichenfolgen in Zahlen umwandelt:
<code class="language-php">// 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)</code>
Die traditionelle BCMath-Erweiterung bietet Präzision:
<code class="language-php">// 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"</code>
Komplexe Berechnungen werden jedoch ausführlicher und weniger wartbar:
<code class="language-php">// Complex order calculation (using BCMath functions) // ... (code omitted for brevity)</code>
Die objektorientierte BCMath-API von PHP 8.4 vereinfacht präzise Berechnungen:
<code class="language-php">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</code>
Vorteile der neuen API:
Stringable
Schnittstellenimplementierung.Weitere Eleganz wird mit den Accessoires von Laravel erreicht:
<code class="language-php">use BCMath\Number; class Item extends Model { // ... (accessor methods for quantity, price, discount, tax using Number) ... }</code>
Oder mit einer individuellen Besetzung:
<code class="language-php">// ... (DecimalCast class implementation) ...</code>
Dann:
<code class="language-php">$item1 = Item::find(1); $subtotal = $item1->price * $item1->quantity; // ... (rest of the calculation) ...</code>
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!