Solution du problème de précision du calcul numérique dans la conception de stratégie JavaScript

Auteur:La bonté, Créé: 2020-07-09 11:31:01, Mis à jour: 2023-10-28 15:32:47

img

Lors de l'écriture de stratégies JavaScript, en raison de certains problèmes du langage de script lui-même, cela conduit souvent à des problèmes de précision numérique dans les calculs.1 - 0.8ou0.33 * 1.1, les données d'erreur sont calculées:

function main() {
    var a = 1 - 0.8
    Log(a)
   
    var c = 0.33 * 1.1
    Log(c) 
}

img

Alors, comment résoudre ces problèmes?

La progression maximale des valeurs en virgule flottante est de 17 décimales, mais la précision est bien pire que celle des entiers lors de l'exécution des opérations; les entiers sont convertis en décimales lors de l'exécution des opérations; et lors du calcul des opérations décimales en Java et JavaScript, les deux Premièrement, convertissez le décimal décimal en binaire correspondant, une partie du décimal ne peut pas être complètement convertie en binaire, voici la première erreur. Après la conversion des décimales en binaire, l'opération entre le binaire est ensuite effectuée pour obtenir le résultat binaire. Ensuite, convertissez le résultat binaire en décimal, où une deuxième erreur se produit généralement.

Afin de résoudre ce problème, j'ai cherché des solutions sur Internet, et j'ai testé et utilisé les solutions suivantes pour résoudre ce problème:

function mathService() {
    // addition
    this.add = function(a, b) {
        var c, d, e;
        try {
            c = a.toString().split(".")[1].length;   // Get the decimal length of a
        } catch (f) {
            c = 0;
        }
        try {
            d = b.toString().split(".")[1].length;   // Get the decimal length of b
        } catch (f) {
            d = 0;
        }
        //Find e first, multiply both a and b by e to convert to integer addition, then divide by e to restore
        return e = Math.pow(10, Math.max(c, d)), (this.mul(a, e) + this.mul(b, e)) / e;
    }
    
    // multiplication
    this.mul = function(a, b) {       
        var c = 0,
            d = a.toString(),         // Convert to string 
            e = b.toString();         // ...
        try {
            c += d.split(".")[1].length;      // c Accumulate the fractional digit length of a
        } catch (f) {}
        try {
            c += e.split(".")[1].length;      // c Accumulate the length of decimal places of b
        } catch (f) {}
        // Convert to integer multiplication, then divide by 10^c, move decimal point, restore, use integer multiplication without losing accuracy
        return Number(d.replace(".", "")) * Number(e.replace(".", "")) / Math.pow(10, c);
    }

    // Subtraction
    this.sub = function(a, b) {
        var c, d, e;
        try {
            c = a.toString().split(".")[1].length;  // Get the decimal length of a
        } catch (f) {
            c = 0;
        }
        try {
            d = b.toString().split(".")[1].length;  // Get the decimal length of b
        } catch (f) {
            d = 0;
        }
        // Same as addition
        return e = Math.pow(10, Math.max(c, d)), (this.mul(a, e) - this.mul(b, e)) / e;
    }

    // Division
    this.div = function(a, b) {
        var c, d, e = 0,
            f = 0;
        try {
            e = a.toString().split(".")[1].length;
        } catch (g) {}
        try {
            f = b.toString().split(".")[1].length;
        } catch (g) {}
        // Similarly, convert to integer, after operation, restore
        return c = Number(a.toString().replace(".", "")), d = Number(b.toString().replace(".", "")), this.mul(c / d, Math.pow(10, f - e));
    }
}

function main() {
    var obj = new mathService()
    
    var a = 1 - 0.8
    Log(a)
    
    var b = obj.sub(1, 0.8)
    Log(b)
    
    var c = 0.33 * 1.1
    Log(c)
    
    var d = obj.mul(0.33, 1.1)
    Log(d)
}

img

Le principe est de convertir les deux opérandes à calculer en entiers pour éviter les problèmes de précision.

De cette façon, lorsque nous voulons que le programme de placer un ordre lorsque le prix du marché plus une précision de prix minimum, nous n'avons pas à nous soucier de la précision numérique

function mathService() {
....    // Omitted
}

function main() {
    var obj = new mathService()
    var depth = exchange.GetDepth()
    exchange.Sell(obj.add(depth.Bids[0].Price, 0.0001), depth.Bids[0].Amount, "Buy 1 order:", depth.Bids[0]) 
}

Les traders intéressés peuvent lire le code, comprendre le processus de calcul, poser des questions, apprendre ensemble et progresser ensemble.


Relationnée

Plus de