Solución del problema de precisión del cálculo numérico en el diseño de estrategias JavaScript

El autor:La bondad, Creado: 2020-07-09 11:31:01, Actualizado: 2023-10-28 15:32:47

img

Cuando se escriben estrategias de JavaScript, debido a algunos problemas del propio lenguaje de scripting, a menudo conduce a problemas de precisión numérica en los cálculos.1 - 0.8o bien0.33 * 1.1, se calcularán los datos de error:

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

img

Entonces, ¿cómo resolver estos problemas?

El progreso máximo de los valores de coma flotante es de 17 decimales, pero la precisión es mucho peor que los enteros al realizar operaciones; los enteros se convierten en decimales al realizar operaciones; y al calcular operaciones decimales en Java y JavaScript, ambos Primero convierte el decimal decimal al binario correspondiente, parte del decimal no se puede convertir completamente a binario, este es el primer error. Después de que los decimales se convierten a binario, luego se realiza la operación entre el binario para obtener el resultado binario. Luego convierte el resultado binario a decimal, donde generalmente ocurre un segundo error.

Para resolver este problema, busqué algunas soluciones en Internet, y probé y usé las siguientes soluciones para resolver este problema:

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

El principio es convertir los dos operandos a calcular en enteros para calcular para evitar problemas de precisión.

De esta manera, cuando queremos que el programa para colocar un pedido cuando el precio de mercado más una precisión de precio mínimo, no tenemos que preocuparnos por la precisión numérica

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]) 
}

Los comerciantes interesados pueden leer el código, entender el proceso de cálculo, invitados a hacer preguntas, aprender juntos y progresar juntos.


Relacionados

Más.