Home > OS >  Why does converting a negative string into a number ( "-2.333" ) return NaN, only when th
Why does converting a negative string into a number ( "-2.333" ) return NaN, only when th

Time:01-09

I am using d3-format's format function to round some numbers (yes, I know this isn't necessary).

When I format negative numbers, I get a string of a negative number, as expected. However, when I convert it back into a number using the shorthand, it returns NaN. This is not what should happen. I should get back a regular negative number.

import {format} from "d3-format"; //version 3.1.0

let numberFormatter = d3.format(".3f");
let neg = -2.333;
let negString = "-2.333";
let d3negString = numberFormatter(neg);

//the strings look the same
console.log(d3negString) // "-2.333"
console.log(negString)   // "-2.333"

//both strings have the same type of 'string'
console.log(typeof negString === typeof d3negString); // true

//but they are not equal
console.log(negString === d3negString); // false 

//normal strings work as expected
console.log(isNaN( negString)); // false

//but strings from d3-format function returns NaN
console.log(isNaN( d3negString)); // true 

It says that both strings have the same type 'string', however their values are not equal?? Even though the text is equal?

What is the true type of d3-formatted number strings? They can't just be normal strings, right? Why is it returning NaN? Is this a bug?

MacOS Big Sur
Chrome 96.0.4664.110
[email protected]

CodePudding user response:

The change log of d3, shows that in version 2.0.0 the following was changed:

Change the default minus sign to the minus sign (−) instead of hyphen-minus (-).

In this thread on D3's github are some interesting comments:

D3 did use the minus sign originally, but people complained about that, too (e.g., #595), primarily because there was an expectation that d3.format would use the same symbol as JavaScript’s number.toString. The minus sign was thus replaced with hyphen-minus in 2.10.0 (da3131c, #756).

And:

This is now available as an opt-in by specifying the locale’s minus property. And I’m considering making the minus sign the default (again) in the next major version.

CodePudding user response:

The reason this doesn't work is because the 'minus' characters, despite appearing identical, are different unicode symbols.

Luckily, d3 provides a way to change the default minus character to whatever you choose using the formatLocale function.]

'HYPHEN-MINUS' U 002D unicode character is recognized as a 'negative sign'.

// import {format} from 'd3-format' //do not directly import format with default settings

import { formatLocale} from "d3-format"
const format  = formatLocale({ minus: "\u002D"}).format 

let numberFormatter = d3.format(".3f");
let neg = -2.333;
let negString = "-2.333";
let d3negString = numberFormatter(neg);
console.log(d3negString) // "-2.333"
console.log(negString)   // "-2.333"
console.log(typeof negString === typeof d3negString); // true
console.log(negString === d3negString); // true 
console.log(isNaN( negString)); // false
console.log(isNaN( d3negString)); // false 

The larger moral of the story is that d3-format's goal is NOT to round numbers - it is to make number look nice as text. To prevent problems, use Math.round() or "-2.3333".toFixed(3) // => -2.333 to round numbers in javascript.

  •  Tags:  
  • Related