Publié à l'origine sur le blog de Takeshi Yu.
Un calcul numérique précis est primordial dans les applications d'entreprise, en particulier celles traitant de la finance, de la comptabilité ou des stocks. Même des erreurs d’arrondi mineures peuvent entraîner des problèmes importants. L'API BCMath Object améliorée de PHP 8.4 offre une solution raffinée pour des calculs décimaux précis et efficaces.
Les développeurs PHP expérimentés sont familiers avec l'imprécision en virgule flottante :
$a = 0.1; $b = 0.2; var_dump($a + $b); // Outputs: 0.30000000000000004
Cette inexactitude est inacceptable dans des contextes financiers. Ces petites erreurs s'accumulent, conduisant à des écarts réels.
Les calculs décimaux précis commencent par la base de données. Le type DECIMAL
est indispensable :
// 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
assure :
Bien que potentiellement légèrement plus lent que FLOAT
, l'avantage en termes de précision l'emporte sur la différence de performances dans les systèmes critiques.
Laravel simplifie la gestion des décimales grâce à son système de conversion :
class Item extends Model { protected $casts = [ 'quantity' => 'decimal:3', 'price' => 'decimal:3', 'discount' => 'decimal:3', 'tax' => 'decimal:3', ]; }
Rappelons cependant que le casting Laravel gère principalement :
Même avec des types de bases de données corrects et un casting Laravel, des erreurs de calcul peuvent survenir :
// 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
Cela se produit parce que PHP convertit implicitement les chaînes en nombres lors de l'arithmétique :
// 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)
L'extension BCMath traditionnelle apporte de la précision :
// 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"
Cependant, les calculs complexes deviennent verbeux et moins maintenables :
// Complex order calculation (using BCMath functions) // ... (code omitted for brevity)
L'API BCMath orientée objet de PHP 8.4 simplifie les calculs précis :
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
Avantages de la nouvelle API :
Stringable
implémentation de l'interface.Une élégance supplémentaire est obtenue avec les accessoires de Laravel :
use BCMath\Number; class Item extends Model { // ... (accessor methods for quantity, price, discount, tax using Number) ... }
Ou avec un casting personnalisé :
// ... (DecimalCast class implementation) ...
Puis :
$item1 = Item::find(1); $subtotal = $item1->price * $item1->quantity; // ... (rest of the calculation) ...
Dans la gestion des stocks de soins de santé, des calculs décimaux précis sont essentiels. L'API BCMath Object de PHP 8.4, intégrée à Laravel, améliore considérablement la gestion de ces calculs, offrant précision, lisibilité, maintenabilité et sécurité des types. Alors que les anciennes fonctions BCMath ont rempli leur objectif, cette nouvelle approche rationalise considérablement le développement.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!