jq icon indicating copy to clipboard operation
jq copied to clipboard

is there way to convert scientific notation numbers to fixed length float

Open jgoodall opened this issue 9 years ago • 15 comments

I have numbers like this 1.26126e-06 in JSON that I would like to convert to 'normal' looking floats (e.g 0.00000126126). Is there an equivalent to printf or JavaScript's toFixed()?

Or is there some other way to set the precision.

jgoodall avatar Aug 03 '16 00:08 jgoodall

At least something like an option to convert float to int dropping the remainder. Then we could at least mock mynumber.toFixed(2) with (mynumber*100 | toInteger) / 100.

MarSoft avatar Jul 03 '19 22:07 MarSoft

I'd like a command line argument to specify the number of digits. FWIW you can do this using Miller (mlr):

$ mlr --json format-values -f '%.9f' <<<'{"x": 1.26126e-6}'
{ "x": 0.000001261 }

sjackman avatar Nov 23 '20 22:11 sjackman

@sjackman mlr --json format-values ... will not handle JSON array correctly (members are pulled out)

honzajde avatar Dec 28 '20 19:12 honzajde

Yeah, Miller handles only tabular JSON files AFAIK.

sjackman avatar Jan 12 '21 19:01 sjackman

@MarSoft This works right now: .*100 | floor | ./100.

jolmg avatar Mar 02 '21 00:03 jolmg

$ jq '.*100 | floor | ./100' <<<'{"hi": "Hello, world!", "frac": 123.456}'
jq: error (at <stdin>:1): object ({"hi":"Hell...) and number (100) cannot be multiplied

sjackman avatar Mar 02 '21 01:03 sjackman

@sjackman jq '(.. | numbers) |= (.*100 | floor | ./100)' <<<'{"hi": "Hello, world!", "frac": 123.456789}'

itchyny avatar Mar 02 '21 01:03 itchyny

That works! Thanks, @itchyny! As a feature request, round could optionally take an accuracy parameter such as round(0.01).

sjackman avatar Mar 02 '21 03:03 sjackman

@sjackman You can substitute floor with round in my suggestion to get the effect you want:

$ jq '.*100 | round | ./100' <<< 123.456789
123.46
$ jq '(.. | numbers) |= (.*100 | round | ./100)' <<<'{"hi": "Hello, world!", "frac": 123.456789}'
{
  "hi": "Hello, world!",
  "frac": 123.46
}

And also define the function you seek:

$ jq 'def round(p): .*(1/p) | round | ./(1/p); round(0.01)' <<< 123.456789
123.46

jolmg avatar Mar 02 '21 19:03 jolmg

@sjackman You can substitute floor with round in my suggestion to get the effect you want:

$ jq '.*100 | round | ./100' <<< 123.456789
123.46
$ jq '(.. | numbers) |= (.*100 | round | ./100)' <<<'{"hi": "Hello, world!", "frac": 123.456789}'
{
  "hi": "Hello, world!",
  "frac": 123.46
}

And also define the function you seek:

$ jq 'def round(p): .*(1/p) | round | ./(1/p); round(0.01)' <<< 123.456789
123.46

can this be adjusted to work with larger numbers?

$ jq 'def round(p): .*(1/p) | round | ./(1/p); round(0.00001)' <<< 0.00004948914415535700
5.000000000000001e-05

ghost avatar Oct 25 '21 08:10 ghost

@arno01 You can simplify the expressions I used. I used those because they seemed clearer to me, but if you limit the operations used, that decreases chances of floating-point rounding errors:

$ jq 'def round(p): ./p | round | .*p; round(0.00001)' <<< 0.00004948914415535700
5e-05

jolmg avatar Oct 26 '21 00:10 jolmg

@arno01 You can simplify the expressions I used. I used those because they seemed clearer to me, but if you limit the operations used, that decreases chances of floating-point rounding errors:

$ jq 'def round(p): ./p | round | .*p; round(0.00001)' <<< 0.00004948914415535700
5e-05

I'd love to get rid of scientific notation though.. if it could turn 0.00004948914415535700 into 0.0000495 that'd be neat :)

ghost avatar Oct 27 '21 14:10 ghost

@arno01 Adding that to jq is what this issue is about. In the mean time, converting that scientific notation would have be done outside. For example, like this:

$ printf '%.7f\n' "$(jq 'def round(p): ./p | round | .*p; round(0.0000001)' <<< 0.00004948914415535700)"
0.0000495

jolmg avatar Oct 27 '21 14:10 jolmg

needed here as well

adrian-gierakowski avatar Jan 04 '23 14:01 adrian-gierakowski

$ echo '{}' | jq '0.1  + 0.2 | .*100 | floor | ./100'
0.3

The expected result should be 0.30

loskael avatar Apr 10 '25 09:04 loskael