Maison >interface Web >js tutoriel >Quelques petites connaissances sur la précision des calculs en javascript (résumé)

Quelques petites connaissances sur la précision des calculs en javascript (résumé)

青灯夜游
青灯夜游original
2018-09-17 15:07:042615parcourir

Ce chapitre vous présentera quelques connaissances de base (résumé) sur la précision des calculs en JavaScript, afin que vous puissiez comprendre comment le binaire est converti entre les décimales, comment JavaScript enregistre les nombres, comment JavaScript lit les nombres et enfin explique avec des exemples comment fonctionne javascript résout les erreurs de calcul causées par des problèmes de précision. Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer. J'espère qu'il vous sera utile.

1. Points de connaissances préalables

1. Comment convertir un nombre décimal en binaire ?

Divisez la partie entière par deux et prenez le reste jusqu'à ce que le quotient soit 0. Disposez dans l'ordre inverse Multipliez la partie décimale par 2 et arrondissez dans l'ordre jusqu'à ce que la partie décimale du produit soit 0 ou. la précision requise est atteinte.

8转为二进制是多少?

8 / 2 = 4...0  取0
4 / 2 = 2...0  取0
2 / 2 = 1...0  取0
1 / 2 = 0...1  取1

二进制结果为:1000

0.25转为二进制是多少?

0.25 * 2 = 0.50  取0
0.50 * 2 = 1.00  取1

二进制结果为:01

于是可得出8.25的二进制表示:1000.01

2. Comment convertir du binaire en décimal ?

Remarque : La conversion du binaire en décimal ne sépare pas la partie entière et la partie décimale.

二进制1000.01转为十进制

1 * 2^3 + 0 * 2^2 + 0 * 2^1 + 0 * 2^0 + 0 * 2^-1 + 0 * 2^-2 = 8.25

2. Comment javascript enregistre-t-il les nombres

Les nombres en JavaScript sont des doubles 64 bits utilisant la norme IEEE 754. Nombre à virgule flottante

  • bit de signe (signe) : utilisé pour représenter le signe positif et négatif, 1 bit (0 signifie positif, 1 signifie négatif)

  • exposant (exposant) : utilisé pour représenter la puissance, 11 chiffres

  • mantisse (mantisse) : utilisé pour représenter la précision, 52 chiffres

Quelques petites connaissances sur la précision des calculs en javascript (résumé)

Pour ceux qui n'ont aucune expérience dans ce domaine, ce qui précède peut être vague à comprendre. Cela n'a pas d'importance. Ensuite, nous utiliserons un cas pour expliquer le processus en détail. , regardons comment le nombre décimal 8,25 mentionné ci-dessus est utilisé dans JS enregistré.

  • Le nombre décimal 8,25 sera converti en binaire 1000,01

  • Le binaire 1000,01 peut être exprimé en notation scientifique binaire 1,00001 * 2^4 ; >

  • 00001 * La partie décimale 00001 (binaire) de 2^4 est la mantisse (mantisse), et 4 (décimal) plus 1023 est l'exposant (exposant) (j'expliquerai pourquoi plus tard Ajouter 1023);

  • Ensuite, l'exposant 4 doit être ajouté à 1023 et converti en binaire 10000000011

  • Notre décimal 8,25 est positif ; nombre, donc le symbole est exprimé en binaire comme 0

  • 8.25 La sauvegarde binaire finale est 0-10000000011-00001000000000000000000000000000000000000000000000000

Remarque :

  • On ajoute 0 s'il n'y a pas assez de chiffres ;

  • On semble avoir oublié la partie entière 1 en notation scientifique obtenue à l'étape 2. Ceci c'est parce que Javascript est utilisé pour faciliter les choses. Pour maximiser la précision, ce 1 est omis, De cette façon, nous ne pouvons sauvegarder que la mantisse (binaire) de 52 bits, mais il y a en réalité 53 bits (binaires)

  • La partie exposant est de 11 bits, et la plage représentée ; est [0, 2047], puisque l'exposant en notation scientifique peut être positif ou négatif, le nombre intermédiaire est 1023, [0,1022] est exprimé comme négatif, [1024,2047] est exprimé comme positif, Cela explique également pourquoi l'exposant dans notre notation scientifique est stocké avec 1023 ajouté.

3. Comment javascript lit-il les nombres

Nous utilisons toujours le binaire 8.25 0-10000000011-00001000000000000000000000 00000000. 0000000000000000 Allons parlons de

  1. Nous obtenons d'abord le binaire 1000000001 de la partie exposant et le convertissons en décimal 1027. 1027 moins 1023 est notre exposant réel 4

  2. Récupérez la partie de la mantisse 0000100000000000000000000000000000000000000000000, qui est en fait 0,00001 (le 0 suivant ne sera pas écrit), puis ajoutez le 1 que nous avons ignoré et obtenez 1,00001 ; 🎜>Parce que le premier morceau est 0, donc notre nombre est un nombre positif, donc la notation scientifique binaire est 1,00001 * 2^4, puis convertie en nombre décimal, nous obtenons notre

  3. 4. Examinant les problèmes de précision de JavaScript à partir de 0,1+0,2

Nous sommes ici sur le point d'arriver au sujet principal. Après avoir compris l'explication du principe précédent, cette partie deviendra très. bien. Je l'ai compris. Pour calculer 0,1+0,2, vous devez d'abord lire ces deux nombres à virgule flottante 0,1 est stocké sous forme de nombre binaire à virgule flottante de 64 bits

N'ai pas oublié le étapes ci-dessus

Convertissez d'abord 0,1 en partie entière binaire en 0, et la partie décimale est : 0001100110011001100110011001100110011... Hé, il y a une boucle infinie ici, que dois-je faire ? Ignorez-le pour l'instant ;

    La boucle infinie de nombres binaires que nous obtenons est exprimée en notation scientifique par 1.100110011001100110011001100110011... * 2^-4 ;
  1. Le bit d'exposant est -4 + 1023 = 1019, et le bit converti est un nombre binaire à 11 chiffres 01111111011 ;

  2. Le bit de mantisse est une boucle infinie, mais double- Les nombres de points flottants de précision nécessitent 52 bits de mantissa, par conséquent, ceux qui dépassent 52 bits seront omis, et 1001100110011001100110011001100110011001111010

  3. seront finalement obtenus en tant que nombre de points de flux binaire 64 bits de 0,1: 0-01111111011-1001 100110011001100110011001100110011001100110011010

同上,0.2存储为64位二进制浮点数:0-01111111100-1001100110011001100110011001100110011001100110011010

读取到两个浮点数的64为二进制后,再将其转化为可计算的二进制数

  1. 0.1转化为1.1001100110011001100110011001100110011001100110011010 * 2^(1019 - 1023)——0.00011001100110011001100110011001100110011001100110011010;

  2. 0.2转化为1.1001100110011001100110011001100110011001100110011010 * 2^(1020 - 1023)——0.0011001100110011001100110011001100110011001100110011010;

接着将两个浮点数的二进制数进行加法运算,得出0.0100110011001100110011001100110011001100110011001100111转化为十进制数即为0.30000000000000004

不难看出,精度缺失是在存储这一步就丢失了,后面的计算只是在不精准的值上进行的运算。

五. javascript如何解决精度问题出现的计算错误问题

对于小数或者整数的简单运算可如下解决:

function numAdd(num1, num2) { 
  let baseNum, baseNum1, baseNum2; 
  try { 
    baseNum1 = String(num1).split(".")[1].length; 
  } catch (e) { 
    baseNum1 = 0; 
  } 
  try { 
    baseNum2 = String(num2).split(".")[1].length; 
  } catch (e) { 
    baseNum2 = 0;
  } 
  baseNum = Math.pow(10, Math.max(baseNum1, baseNum2));
  return (num1 * baseNum + num2 * baseNum) / baseNum;
};

如:0.1 + 0.2 通过函数处理后,相当于 (0.1 * 10 + 0.2 * 10) / 10

但是如同我们前面所了解的,浮点数在存储的时候就已经丢失精度了,所以浮点数乘以一个基数仍然会存在精度缺失问题,比如2500.01 * 100 = 250001.00000000003, 所以我们可以在以上函数的结果之上使用toFixed(),保留需要的小数位数。

一些复杂的计算,可以引入一些库进行解决


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!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn