Calcul sans erreur avec le big.Float de Golang

introduction

Lorsque vous utilisez golang pour exécuter les quatre règles de l'ETH, un calcul en virgule flottante avec 18 chiffres après la virgule décimale est requis. Si vous n'êtes pas conscient du dépassement, il y aura des erreurs dans le calcul, utilisez donc le type virgule flottante double précision dans l'utilisation correcte.

essayons

Les choses nécessaires

seulement golang

Quel genre d'erreur se produira?

L'ETH est soustrait du budget de 1000 ETH, puis rajouté. S'il n'y a pas d'erreur, il devrait revenir à 1000 ETH.

error.go


package main

import (
	"fmt"
	"math/big"
	"strings"
)

func main() {
	budget, _ := new(big.Float).SetString("1000")
	amount, _ := new(big.Float).SetString("0.123456789012345678")
	balance := new(big.Float).Sub(budget, amount)
	summary := new(big.Float).SetPrec(128).Add(balance, amount)

	fmt.Printf("budget  = %v\n", formatFloatPrice(budget, 18))
	fmt.Printf("amount  = %v\n\n", formatFloatPrice(amount, 18))

	fmt.Printf("balance = budget - amount = %v\n", formatFloatPrice(balance, 18))
	fmt.Printf("budget = balance + amount = %v\n", formatFloatPrice(summary, 18))
}

func formatFloatPrice(amount *big.Float, decimals int) string {
	str := amount.Text('f', decimals)
	if strings.Contains(str, ".") {
		str = strings.TrimRight(str, "0")
		if strings.HasSuffix(str, ".") {
			str = str + "0"
		}
	}
	return str
}

Quand je l'exécute, cela devrait être 1000 ETH, mais cela ne fonctionne pas à cause de l'erreur.

Résultat d'exécution


budget  = 1000.0
amount  = 0.123456789012345678

balance = budget - amount = 999.876543210987654309
budget = balance + amount = 999.999999999999999987

Comment éliminer l'erreur?

Utilisez la méthode magique SetPrec () pour améliorer la précision des fractions flottantes.

ok.go


package main

import (
	"fmt"
	"math/big"
	"strings"
)

func main() {
	budget, _ := new(big.Float).SetPrec(128).SetString("1000")
	amount, _ := new(big.Float).SetPrec(128).SetString("0.123456789012345678")
	balance := new(big.Float).SetPrec(128).Sub(budget, amount)

	summary := new(big.Float).SetPrec(128).Add(balance, amount)

	fmt.Printf("budget  = %v\n", formatFloatPrice(budget, 18))
	fmt.Printf("amount  = %v\n\n", formatFloatPrice(amount, 18))

	fmt.Printf("balance = budget - amount = %v\n", formatFloatPrice(balance, 18))
	fmt.Printf("budget = balance + amount = %v\n", formatFloatPrice(summary, 18))
}

func formatFloatPrice(amount *big.Float, decimals int) string {
	str := amount.Text('f', decimals)
	if strings.Contains(str, ".") {
		str = strings.TrimRight(str, "0")
		if strings.HasSuffix(str, ".") {
			str = str + "0"
		}
	}
	return str
}

Je suis revenu à 1000 ETH en toute sécurité!

Résultat d'exécution


budget  = 1000.0
amount  = 0.123456789012345678

balance = budget - amount = 999.876543210987654322
budget = balance + amount = 1000.0

Recommended Posts

Calcul sans erreur avec le big.Float de Golang
L'histoire du calcul numérique des équations différentielles avec TensorFlow 2.0
1. Statistiques apprises avec Python 1-3. Calcul de diverses statistiques (statistiques)
Calcul en temps réel de la valeur moyenne avec corroutine
1. Statistiques apprises avec Python 1-2. Calcul de diverses statistiques (Numpy)
Calcul séquentiel de la valeur moyenne avec l'algorithme en ligne
Calcul de la quantité d'informations mutuelles (valeur continue) avec numpy
Effectue le calcul à grande vitesse de descripteurs spécifiques uniquement avec mordred
Essayez d'obtenir le contenu de Word avec Golang
Appeler bash avec Golang
Calcul numérique avec Python
Comment activer la lecture / écriture de net.Conn avec Golang pour annuler avec le contexte
Premiers pas avec PKI avec Golang ―― 4
[Python] Méthode de calcul avec numpy
Equation de mouvement avec sympy
Traitement parallèle avec Parallel de scikit-learn
Calcul de similitude par MinHash
Prédiction de la moyenne Nikkei avec Pytorch 2
Souvenirs de combats avec Selenium
À propos du calcul des coûts de MeCab
Prédiction de la moyenne Nikkei avec Pytorch