Plateforme

Différences de JavaScript Math entre navigateurs

Les garanties d’ECMAScript pour Math, la marge des implémentations et les tests de calculs portables sans en faire une identité.

Documentation

Vous voulez la documentation structurée pour Plateforme ?

Cet article fait partie de la bibliothèque éditoriale. Pour les étapes de configuration, la référence et les mises à jour continues, passez directement à la section docs.

ECMAScript définit l’objet Math de JavaScript, mais ne garantit pas des résultats identiques bit à bit pour chaque opération mathématique dans tous les navigateurs. Les valeurs Number ordinaires utilisent la représentation binary64, donc l’arrondi fait partie du modèle numérique. De nombreuses opérations ont un comportement précisément défini, tandis que certaines fonctions mathématiques permettent une approximation selon les règles du standard. Une application doit préciser la précision nécessaire à ses tâches et tester ce contrat, au lieu de déduire un comportement universel des navigateurs à partir d’une valeur observée.

Ces détails comptent lorsqu’un résultat commande une décision, est conservé ou passe d’un système à un autre. Une expression décimale ne se représente pas nécessairement exactement en binaire, et la valeur peut ensuite être analysée, convertie, formatée et stockée. Considérez tout ce parcours comme une partie du contrat numérique de l’application. Un résultat adapté à l’affichage ne convient pas forcément à la comptabilité ou à une décision de frontière sans règle explicite d’arrondi.

Ce que spécifie ECMAScript

La distinction dépend de l’opération. Math.exp définit exactement le traitement de NaN, des infinis et du zéro signé, puis autorise un résultat approché par l’implémentation pour les autres entrées. Math.round impose au contraire de départager deux entiers équidistants vers l’infini positif et conserve les entrées non finies et entières. Ce n’est pas la règle financière d’arrondi des égalités au chiffre pair. Consultez le contrat précis pour distinguer une approximation permise d’une attente erronée de l’application ; n’élargissez pas toutes les tolérances parce qu’une autre fonction de Math autorise une approximation.

ECMAScript définit les opérations de Math et leur comportement observable. La spécification de l’objet Math donne les exigences propres à chaque opération. Certains résultats sont déterminés de manière stricte. D’autres fonctions, dont les résultats réels ne sont généralement pas représentables exactement en binary64, peuvent laisser une marge d’approximation limitée par le standard. Cette marge n’autorise pas n’importe quelle sortie. Pour une différence qui touche l’application, identifiez l’opération et consultez son exigence précise au lieu de généraliser à partir d’un exemple.

La précision finie explique de nombreux résultats parfois surprenants. La virgule flottante binaire stocke une combinaison finie de puissances de deux, et plusieurs fractions décimales courantes n’ont pas de représentation exacte dans ce système. Un arrondi peut donc survenir pendant une opération ou une conversion. Des expressions apparemment équivalentes peuvent aussi arrondir leurs résultats intermédiaires dans un ordre différent. Ce sont des conséquences normales de la représentation, même si une application peut faire une supposition inexacte en exigeant une égalité décimale ou en choisissant un algorithme inadapté.

Le code JavaScript ajoute d’autres frontières numériques autour de Math. L’analyse du texte, les entrées JSON, la coercition implicite, la conversion d’entiers en Number et la sérialisation des sorties peuvent modifier une valeur avant ou après l’opération. Si deux navigateurs semblent diverger, gardez les entrées et la sérialisation fixes, puis examinez l’opération entre les deux. Sinon, un changement de fixture ou de conversion peut passer pour une différence du runtime. La version du navigateur n’explique pas à elle seule chaque résultat numérique.

Le contrat dépend aussi du domaine de l’application. Un total monétaire, une coordonnée graphique et un score statistique n’ont pas les mêmes besoins de plage, de précision ni de marge d’erreur. Décidez du résultat correct pour la tâche utilisateur et exprimez cette règle dans un test. Ne laissez pas une forme décimale affichée ou les derniers chiffres représentables d’une implémentation devenir une exigence accidentelle du produit, sauf si l’application en dépend explicitement.

L’application doit expliciter le passage d’une valeur mathématique à sa valeur présentée. Une quantité calculée peut être plus précise que l’affichage ; la forme visible ne doit pas remplacer silencieusement la valeur stockée, sauf si telle est la règle voulue. Un outil de mesure peut conserver sa précision pour les calculs ultérieurs tout en montrant une lecture arrondie. Un parcours de paiement peut au contraire nécessiter un arrondi défini avant l’enregistrement. Indiquez quelle représentation fait autorité à chaque frontière et appliquez la même politique aux exports. Ainsi, écran, fichier téléchargé et calcul ultérieur ne divergent pas à cause de conversions implicites différentes. Le contrat dépend du domaine ; un test de compatibilité ne doit pas imposer un nombre universel de décimales.

Points de vigilance pour la portabilité

La politique d’arrondi doit être délibérée à chaque frontière. Une application peut garder une précision interne et n’arrondir qu’à l’affichage. Un système qui stocke des montants décimaux saisis par les utilisateurs peut utiliser des entiers mis à l’échelle ou une bibliothèque décimale. Ces choix répondent à des contrats différents. Arrondir trop tôt fait perdre de l’information ; reporter indéfiniment l’arrondi sans règle peut produire des totaux incohérents aux yeux des utilisateurs. Précisez où arrondir lors du stockage, de l’échange ou de la présentation, puis appliquez ce choix dans tout le parcours.

L’ordre des opérations peut modifier les résultats en virgule flottante. Des formules équivalentes en algèbre ne produisent pas toujours les mêmes arrondis intermédiaires avec une précision finie. Une refactorisation peut donc changer les derniers chiffres représentables sans enfreindre ECMAScript. Si la stabilité numérique compte, choisissez un algorithme adapté au problème et testez-le avec des entrées pertinentes. N’envisagez une correction propre à un navigateur qu’après avoir vérifié le besoin numérique et la spécification de l’opération. Sinon, une solution de contournement peut conserver une attente accidentelle et dégrader le calcul réel.

Les comparaisons aux frontières méritent de l’attention, car un faible écart d’arrondi peut choisir une autre branche. Pour les décisions d’éligibilité, de facturation ou de sécurité, définissez le traitement des égalités et précisez si la comparaison a lieu avant ou après l’arrondi d’affichage. Testez les valeurs de part et d’autre de la frontière utile. L’application doit également décider comment gérer les résultats non finis, les entrées invalides et le zéro signé lorsqu’ils sont possibles. Rejeter, normaliser ou signaler ces valeurs doit être un choix explicite, pas un effet fortuit de la sérialisation ou du formatage.

Les dépendances et les interfaces hôtes apportent leurs propres comportements numériques. Une bibliothèque peut utiliser un autre algorithme ou une autre politique d’arrondi, et un serveur ou une base de données peut représenter les nombres différemment de JavaScript. Pour les valeurs échangées, définissez la représentation transmise et testez tout le trajet, de l’analyse au stockage en passant par le calcul et la sérialisation. Les grands entiers et les quantités décimales exactes peuvent nécessiter une chaîne ou une structure explicite plutôt qu’un nombre JSON générique en virgule flottante. Le séparateur décimal localisé modifie la présentation, pas la valeur sous-jacente.

La même attention s’impose lorsque la valeur change de langage ou de système. Un langage serveur peut distinguer les types entiers et décimaux, tandis qu’une colonne de base de données impose sa propre échelle ou plage. Convertir en Number JavaScript puis revenir peut perdre des distinctions que le système source représentait. Décidez si l’interface transmet un entier, une chaîne décimale ou une structure, puis validez-la aux deux extrémités. Testez les limites prises en charge ainsi qu’un aller-retour par le stockage. Si une valeur sert seulement à l’affichage, identifiez-la comme telle et ne renvoyez pas la chaîne formatée comme entrée de calcul. Un contrat explicite est plus portable que des conversions implicites propres au navigateur et au service. Documentez la représentation qui fait autorité après l’enregistrement et réutilisez-la lors du chargement. L’utilisateur ne devrait pas voir la valeur arrondie affichée devenir l’entrée du calcul suivant, sauf si cette règle fait partie du produit. Des fixtures synthétiques suffisent à vérifier cet aller-retour sans ajouter de dossiers personnels aux tests. Si un service refuse une valeur hors de sa plage, renvoyez un résultat de validation clair au lieu de la réduire silencieusement. Ces choix relient la précision numérique au fonctionnement normal de l’application et rendent les tests de navigateur utiles à sa maintenance.

Contexte de confidentialité

Les résultats numériques sont observables, mais une valeur issue de Math n’établit ni l’identité de l’utilisateur ni le navigateur utilisé. Elle peut dépendre des entrées, du code applicatif, de la version du runtime et du contexte des données. Traiter une valeur comme une identité stable introduit des hypothèses de suivi injustifiées et fragilise l’application. Ne recueillez pas les sorties numériques si la fonction n’en a pas besoin et ne les liez pas à des dossiers persistants sans objectif ni règle de conservation clairs.

Les diagnostics doivent rester proportionnés au problème. Lorsqu’un utilisateur signale un calcul incorrect, une reproduction minimale avec des entrées synthétiques est généralement préférable à la collecte de ses données sous-jacentes. Consignez l’opération et la version applicative pertinente, pas des données étrangères au problème. Si le support a besoin d’entrées réelles, obtenez-les par un processus approprié contrôlé par l’utilisateur et définissez l’accès et la suppression avant la collecte. Séparez les preuves temporaires d’ingénierie des statistiques produit et supprimez-les à la fin du besoin de support.

La confidentialité dépend également du traitement autour du calcul. Expliquez si les valeurs restent dans la page, sont envoyées à un service ou sont conservées après la tâche. Une bibliothèque standard ne décide pas de ces pratiques. Évitez de joindre les diagnostics à des données de compte ou de navigation sans lien avec le problème. Une assistance de compatibilité peut nécessiter la version du navigateur et le résultat fonctionnel, sans devoir conserver toutes les valeurs calculées. Les données recueillies doivent répondre à la question de support, sans élargir son objet.

Ce sujet concerne la sémantique numérique, pas la précision des horloges ou l’aléatoire avec graine. Ces sujets sont traités séparément dans les signaux de timing du navigateur et le comportement déterministe du navigateur. Sans preuve, ne décrivez pas un résultat de Math comme une identité personnelle, un modèle d’appareil ou la preuve d’une plateforme. Une description exacte du flux de données applicatif est plus utile qu’une promesse absolue de confidentialité ou une affirmation de plateforme sans fondement.

Cette distinction compte pour les diagnostics recueillis par l’application. Un rapport de support contenant un résultat doit expliquer pourquoi il est nécessaire et s’il comprend des données utilisateur. Souvent, l’opération se reproduit avec des valeurs générées qui ne révèlent aucun dossier personnel. Si le support a besoin de l’entrée réelle, limitez la demande au cas concerné et suivez le processus habituel de consentement et de suppression. Ne conservez pas d’historique de calculs sans rapport parce que les nombres sont faciles à journaliser. Un tel historique peut révéler les habitudes d’une personne sans aider à vérifier un contrat applicatif précis. Un diagnostic temporaire lié à un signalement est plus facile à examiner et supprimer qu’un registre général des calculs.

Écrire des tests numériques reproductibles

Commencez par les opérations réellement utilisées par l’application. Pour chacune, définissez des entrées représentatives, le comportement attendu dans le domaine et la règle de comparaison. L’égalité exacte convient lorsque le contrat l’exige, par exemple pour des identifiants entiers ou une valeur arrondie volontairement dans une représentation définie. Pour les calculs approximatifs, choisissez une tolérance justifiée par la tâche, l’échelle du résultat et l’erreur attendue. Une tolérance fixe peut convenir à une plage étroite et devenir inadaptée sur plusieurs ordres de grandeur.

Dans un petit jeu de données synthétiques, la règle d’arrondi des égalités spécifiée pour Math.round donne 3 pour l’entrée 2.5 ; tout autre résultat doit faire échouer l’assertion, et non conduire à élargir la tolérance. Ce test porte sur cette règle standard précise, pas sur une politique de paiement : un contrat de facturation fondé sur l’arrondi au pair nécessite sa propre opération et son propre résultat attendu.

Pour un formulaire de paiement où le montant est obligatoire, un champ vide doit afficher un message indiquant qu’il est requis et ne pas envoyer le formulaire, plutôt que créer une transaction de montant nul. Pour une facture enregistrée dont le montant canonique est la chaîne décimale 12.50, une mise à jour du formatage dans le seul navigateur doit laisser ce montant inchangé ; si le schéma stocké doit évoluer, testez une migration explicite avec des données synthétiques avant de le remplacer.

Testez aussi les limites pertinentes, pas seulement les valeurs habituelles. Incluez des entrées proches des frontières du domaine, zéro, des valeurs négatives si elles sont admises, des magnitudes proches de la plage prise en charge et des cas invalides ou exceptionnels. Des calculs répétés peuvent accumuler de petites erreurs même si une opération isolée est acceptable ; testez donc la séquence réellement effectuée par l’application. Il ne s’agit pas de cataloguer toutes les sorties possibles de Math, mais de couvrir les situations numériques qui peuvent changer le résultat visible ou enfreindre le contrat métier.

Vérifiez la représentation dans toute l’interface. Si les valeurs sont sérialisées, stockées ou échangées avec un service, contrôlez le trajet complet plutôt que le seul calcul côté navigateur. Les nombres JSON, chaînes formatées, colonnes de base de données et bindings de langages ont chacun leurs règles. Définissez quel composant arrondit et comment la précision est préservée. Séparez formatage local et valeur numérique afin qu’un séparateur ne ressemble pas à un écart arithmétique. Si une sérialisation déterministe est requise, spécifiez son encodage à la frontière applicative et ne normalisez que ce que le contrat autorise.

Gardez les fixtures petites, synthétiques et liées à une règle visible par l’utilisateur. Un cas limite doit expliquer son utilité ; une grande valeur doit indiquer la plage testée. Lors d’une enquête, notez les versions du runtime et de l’application, et rattachez l’attente au domaine plutôt qu’à un résultat capturé sur un seul poste. Séparez les tests unitaires d’une opération des tests du parcours complet, de l’analyse au stockage en passant par le calcul et le formatage. Ils détectent des changements différents et orientent mieux la maintenance.

Les données de test doivent refléter les modes d’entrée dans l’application, pas seulement des valeurs créées dans le code. Un nombre saisi dans un formulaire peut contenir des espaces, un séparateur localisé ou un champ vide. Le parseur doit accepter une forme documentée ou fournir une validation claire. Une fois la valeur analysée, la fonction numérique se teste séparément. Cette séparation aide à savoir si un résultat affiché différent vient de l’analyse, du calcul ou de la présentation. Utilisez des fixtures synthétiques représentatives et n’ajoutez pas de dossiers réels à la suite. Si une règle métier change, mettez à jour l’explication utilisateur et le résultat attendu pour que la raison soit visible.

Examiner les versions du navigateur

Si une mise à jour change un test numérique, gardez fixes la révision applicative, la fixture d’entrée et l’assertion, puis réduisez le premier cas divergent. Vérifiez si l’opération est strictement définie ou permet une approximation. Avant d’incriminer le navigateur, examinez les conversions, les versions de dépendances, les changements applicatifs et la sérialisation. Si l’assertion était plus stricte que le contrat métier, corrigez-la avec une justification explicite. N’élargissez pas les tolérances seulement pour faire disparaître un écart inexpliqué, car cela peut masquer un vrai problème applicatif.

Une comparaison contrôlée ne change qu’une variable pertinente à la fois. Une mise à jour du navigateur peut coïncider avec celle d’une bibliothèque système, du bundle applicatif, du jeu de données ou du code compilé. Notez l’environnement nécessaire à la reproduction, sans recueillir de détails superflus sur la machine. Si l’écart apparaît après une mise à jour de dépendance ou d’application, comparez séparément ces révisions. Aucune règle générale ne donne un comportement numérique unique à une famille de navigateurs pour toutes les opérations et versions.

Les performances et la correction sont deux sujets distincts. Si un calcul affecte la réactivité, mesurez le parcours utilisateur avec des données représentatives et précisez la charge. Ne convertissez pas la durée en étiquette de navigateur ou d’appareil. Le matériel, l’activité de fond, l’état d’alimentation et les changements du runtime influencent le temps, alors qu’un résultat rapide ne prouve pas la correction numérique. Gardez les observations de performance dans des tests séparés et utilisez le contrat numérique pour l’acceptation fonctionnelle.

Appliquez la même discipline aux bibliothèques numériques, aux compilateurs et aux données stockées. Une dépendance peut changer d’algorithme, un compilateur peut modifier l’évaluation et une valeur persistée peut avoir traversé une autre représentation. Maintenez une petite suite de régression qui explique chaque fixture et réexaminez-la lorsque les exigences du domaine ou la plage de navigateurs supportés changent. Avant une mise en production, consignez le parcours applicatif concerné et l’action éventuelle pour les utilisateurs, sans révéler leurs valeurs ni promettre une identité bit à bit universelle. La revue des versions du navigateur aide à distinguer les changements du runtime de ceux de l’application.

Lorsqu’une version change un parcours numérique, examinez aussi les données stockées. Si l’application arrondissait auparavant à une autre étape, les anciens enregistrements peuvent suivre cette règle. Décidez s’ils restent valides, nécessitent une migration ponctuelle ou doivent garder leur forme d’origine. Ne réécrivez pas les valeurs persistées pour les faire ressembler aux résultats d’un nouveau navigateur. Celui-ci n’a peut-être pas créé les données, et un changement de stockage peut toucher tous les clients. Donnez à la migration une raison métier, une procédure vérifiable lorsque c’est possible et un test avec des dossiers synthétiques. Ne demandez une action aux utilisateurs que si elle est réellement nécessaire. Classez les fixtures par usage afin de distinguer les changements du runtime, des dépendances et de l’application.

Un besoin numérique définit un contrat portable et des tests entre runtimes.

Sources publiques

#JavaScript#ECMAScript#Math#Compatibilité Navigateur

Faites passer BotBrowser de la recherche à la production

Utilisez ces guides pour comprendre le modèle, puis passez à la validation multi-plateforme, aux contextes isolés et au déploiement navigateur prêt pour l'échelle.