Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
// MODULES //

// NOTE: for the following, we explicitly avoid using stdlib packages in this particular package in order to avoid circular dependencies.
var abs = Math.abs; // eslint-disable-line stdlib/no-builtin-math
var lowercase = String.prototype.toLowerCase;
var uppercase = String.prototype.toUpperCase;
var replace = String.prototype.replace;
Expand All @@ -31,9 +30,11 @@ var replace = String.prototype.replace;

var RE_EXP_POS_DIGITS = /e\+(\d)$/;
var RE_EXP_NEG_DIGITS = /e-(\d)$/;
var RE_ONLY_DIGITS = /^(\d+)$/;
var RE_DIGITS_BEFORE_EXP = /^(\d+)e/;
var RE_TRAILING_PERIOD_ZERO = /\.0$/;
var RE_ONLY_DIGITS = /^(-?\d+)$/;
var RE_DIGITS_BEFORE_EXP = /^(-?\d+)e/;
var RE_EXP = /e([+-]\d+)$/;
var RE_TRAILING_ZEROS = /(\.\d*?)0+$/;
var RE_TRAILING_PERIOD = /\.$/;
var RE_PERIOD_ZERO_EXP = /\.0*e/;
var RE_ZERO_BEFORE_EXP = /(\..*[^0])0*e/;

Expand All @@ -51,6 +52,7 @@ var RE_ZERO_BEFORE_EXP = /(\..*[^0])0*e/;
*/
function formatDouble( f, token ) {
var digits;
var exp;
var out;

switch ( token.specifier ) {
Expand All @@ -64,19 +66,23 @@ function formatDouble( f, token ) {
break;
case 'g':
case 'G':
if ( abs( f ) < 0.0001 ) {
digits = token.precision;
if ( digits > 0 ) {
digits -= 1;
// A precision of zero is treated as one significant digit:
digits = ( token.precision > 0 ) ? token.precision : 1;

// Use the exponent of the value rounded to `digits` significant digits to choose between exponential and fixed-point notation, as in C's `printf`:
out = f.toExponential( digits - 1 );
exp = RE_EXP.exec( out );
if ( exp ) {
exp = parseInt( exp[ 1 ], 10 );
if ( exp >= -4 && exp < digits ) {
out = f.toFixed( digits - 1 - exp );
}
out = f.toExponential( digits );
} else {
out = f.toPrecision( token.precision );
}
if ( !token.alternate ) {
out = replace.call( out, RE_ZERO_BEFORE_EXP, '$1e' );
out = replace.call( out, RE_PERIOD_ZERO_EXP, 'e' );
out = replace.call( out, RE_TRAILING_PERIOD_ZERO, '' );
out = replace.call( out, RE_TRAILING_ZEROS, '$1' );
out = replace.call( out, RE_TRAILING_PERIOD, '' );
}
break;
default:
Expand Down
117 changes: 117 additions & 0 deletions lib/node_modules/@stdlib/string/base/format-interpolate/test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -796,6 +796,123 @@ tape( 'the function returns a formatted string (`G` specifier, alternate form)',
t.end();
});

tape( 'the function returns a formatted string (`g` specifier, trailing zeros)', function test( t ) {
var expected;
var values;
var actual;
var tokens;
var i;

tokens = formatTokenize( '%g' );
values = [ 1.5, -2.5, 100, 0.5, 0.0001, 123.0, 1.0e-5 ];
expected = [ '1.5', '-2.5', '100', '0.5', '0.0001', '123', '1e-05' ];
for ( i = 0; i < values.length; i++ ) {
actual = formatInterpolate( tokens, values[ i ] );
t.strictEqual( actual, expected[ i ], 'returns expected output' );
}

tokens = formatTokenize( '%.3g' );
actual = formatInterpolate( tokens, 0.1 );
expected = '0.1';
t.strictEqual( actual, expected, 'returns expected output' );

tokens = formatTokenize( '%10g|' );
actual = formatInterpolate( tokens, 1.5 );
expected = ' 1.5|';
t.strictEqual( actual, expected, 'returns expected output' );

tokens = formatTokenize( '%G' );
actual = formatInterpolate( tokens, 0.5 );
expected = '0.5';
t.strictEqual( actual, expected, 'returns expected output' );

t.end();
});

tape( 'the function returns a formatted string (`g` specifier, zero)', function test( t ) {
var expected;
var tokens;
var actual;

tokens = formatTokenize( '%g' );
actual = formatInterpolate( tokens, 0 );
expected = '0';
t.strictEqual( actual, expected, 'returns expected output' );

tokens = formatTokenize( '%#g' );
actual = formatInterpolate( tokens, 0 );
expected = '0.00000';
t.strictEqual( actual, expected, 'returns expected output' );

t.end();
});

tape( 'the function returns a formatted string (`g` specifier, zero precision)', function test( t ) {
var expected;
var tokens;
var actual;

tokens = formatTokenize( '%.0g' );
actual = formatInterpolate( tokens, 1.5 );
expected = '2';
t.strictEqual( actual, expected, 'returns expected output' );

tokens = formatTokenize( '%.0g' );
actual = formatInterpolate( tokens, 15 );
expected = '2e+01';
t.strictEqual( actual, expected, 'returns expected output' );

t.end();
});

tape( 'the function returns a formatted string (`g` specifier, switching between fixed-point and exponential notation)', function test( t ) {
var expected;
var tokens;
var actual;

tokens = formatTokenize( '%g' );
actual = formatInterpolate( tokens, 123456 );
expected = '123456';
t.strictEqual( actual, expected, 'returns expected output' );

actual = formatInterpolate( tokens, 1234567 );
expected = '1.23457e+06';
t.strictEqual( actual, expected, 'returns expected output' );

actual = formatInterpolate( tokens, 999999.5 );
expected = '1e+06';
t.strictEqual( actual, expected, 'returns expected output' );

actual = formatInterpolate( tokens, 0.00009999995 );
expected = '0.0001';
t.strictEqual( actual, expected, 'returns expected output' );

t.end();
});

tape( 'the function returns a formatted string (`g` specifier, alternate form, negative values)', function test( t ) {
var expected;
var tokens;
var actual;

tokens = formatTokenize( '%#.3g' );
actual = formatInterpolate( tokens, -340.12 );
expected = '-340.';
t.strictEqual( actual, expected, 'returns expected output' );

tokens = formatTokenize( '%#g' );
actual = formatInterpolate( tokens, -1.5 );
expected = '-1.50000';
t.strictEqual( actual, expected, 'returns expected output' );

tokens = formatTokenize( '%#.0f' );
actual = formatInterpolate( tokens, -3 );
expected = '-3.';
t.strictEqual( actual, expected, 'returns expected output' );

t.end();
});

tape( 'the function returns a formatted string (`f` specifier, minimum width)', function test( t ) {
var expected;
var tokens;
Expand Down
Loading