Skip to content

Commit

Permalink
Support different precision for unit measures in human number printin…
Browse files Browse the repository at this point in the history
  • Loading branch information
renggli committed Sep 27, 2023
1 parent 5b6aff4 commit e554d04
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 16 deletions.
50 changes: 36 additions & 14 deletions lib/src/printer/number/human.dart
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,21 @@ class HumanNumberPrinter<T extends num> extends Printer<T> {
this.sign,
this.unitBase = 10,
this.unitOffset = 0,
this.unitPrecision = 0,
this.unitPrefix = false,
this.unitSeparator = ' ',
}) : _mantissa = FixedNumberPrinter(
}) : _unit = FixedNumberPrinter(
base: base,
characters: characters,
delimiter: delimiter,
infinity: infinity,
nan: nan,
padding: padding,
precision: unitPrecision,
separator: separator,
sign: sign ?? const SignNumberPrinter<double>.omitPositiveSign(),
),
_scaled = FixedNumberPrinter(
base: base,
characters: characters,
delimiter: delimiter,
Expand All @@ -119,11 +131,12 @@ class HumanNumberPrinter<T extends num> extends Printer<T> {
int precision = 0,
String separator = '',
Printer<double>? sign,
int unitPrecision = 0,
bool unitPrefix = false,
String unitSeparator = ' ',
}) =>
HumanNumberPrinter(
base: base = 10,
base: base,
characters: characters,
delimiter: delimiter,
infinity: infinity,
Expand All @@ -132,10 +145,11 @@ class HumanNumberPrinter<T extends num> extends Printer<T> {
precision: precision,
separator: separator,
sign: sign,
unitPrefix: unitPrefix,
unitSeparator: unitSeparator,
unitBase: decimalUnitBase,
unitOffset: decimalUnitOffset,
unitPrecision: unitPrecision,
unitPrefix: unitPrefix,
unitSeparator: unitSeparator,
units: long ? decimalUnitsLong : decimalUnitsShort,
);

Expand All @@ -153,6 +167,7 @@ class HumanNumberPrinter<T extends num> extends Printer<T> {
int padding = 0,
int precision = 0,
String separator = '',
int unitPrecision = 0,
Printer<double>? sign,
bool unitPrefix = false,
String unitSeparator = ' ',
Expand All @@ -167,9 +182,11 @@ class HumanNumberPrinter<T extends num> extends Printer<T> {
precision: precision,
separator: separator,
sign: sign,
unitBase: binaryUnitBase,
unitOffset: binaryUnitOffset,
unitPrecision: unitPrecision,
unitPrefix: unitPrefix,
unitSeparator: unitSeparator,
unitBase: binaryUnitBase,
units: long ? binaryUnitsLong : binaryUnitsShort,
);

Expand Down Expand Up @@ -209,34 +226,39 @@ class HumanNumberPrinter<T extends num> extends Printer<T> {
/// Whether the unit should be used as a prefix, instead of an suffix.
final bool unitPrefix;

/// The number of digits to be printed for unit numbers.
final int unitPrecision;

/// Separator between value and unit.
final String unitSeparator;

/// The units to be used.
final List<String> units;

/// The (internal) printer of the mantissa.
final Printer<double> _mantissa;
/// The printer for integral values.
final Printer<double> _unit;

/// The printer for scaled values.
final Printer<double> _scaled;

@override
void printOn(T object, StringBuffer buffer) {
final value = object.toDouble();
if (value.isInfinite || value.isNaN) {
_mantissa.printOn(value, buffer);
_unit.printOn(value, buffer);
} else {
final index = _getExponent(value) + unitOffset;
final unitIndex = index.clamp(0, units.length - 1);
final unitString = units[unitIndex];
final unitExponent = unitIndex - unitOffset;
final mantissa = value / unitBase.toDouble().pow(unitExponent);
if (unitString.isEmpty) {
_mantissa.printOn(mantissa, buffer);
} else if (unitPrefix) {
if (unitString.isNotEmpty && unitPrefix) {
buffer.write(unitString);
buffer.write(unitSeparator);
_mantissa.printOn(mantissa, buffer);
} else {
_mantissa.printOn(mantissa, buffer);
}
final printer = unitIndex == unitOffset ? _unit : _scaled;
printer.printOn(mantissa, buffer);
if (unitString.isNotEmpty && !unitPrefix) {
buffer.write(unitSeparator);
buffer.write(unitString);
}
Expand Down
50 changes: 48 additions & 2 deletions test/printer_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -528,11 +528,34 @@ void main() {
final printer = HumanNumberPrinter.decimal(nan: 'n/a');
expect(printer(double.nan), 'n/a');
});
test('nan', () {
test('infinity', () {
final printer = HumanNumberPrinter.decimal(infinity: 'huge');
expect(printer(double.infinity), 'huge');
expect(printer(double.negativeInfinity), '-huge');
});
test('precision', () {
final printer = HumanNumberPrinter.decimal(precision: 1);
expect(printer(0), '0');
expect(printer(27), '27');
expect(printer(999), '999');
expect(printer(1000), '1.0 k');
expect(printer(1023), '1.0 k');
expect(printer(1024), '1.0 k');
expect(printer(1728), '1.7 k');
expect(printer(1855425871872), '1.9 T');
});
test('unitPrecision', () {
final printer =
HumanNumberPrinter.decimal(precision: 2, unitPrecision: 1);
expect(printer(0), '0.0');
expect(printer(27), '27.0');
expect(printer(999), '999.0');
expect(printer(1000), '1.00 k');
expect(printer(1023), '1.02 k');
expect(printer(1024), '1.02 k');
expect(printer(1728), '1.73 k');
expect(printer(1855425871872), '1.86 T');
});
test('unitPrefix', () {
final printer = HumanNumberPrinter.decimal(unitPrefix: true);
expect(printer(4), '4');
Expand Down Expand Up @@ -595,11 +618,34 @@ void main() {
final printer = HumanNumberPrinter.binary(nan: 'n/a');
expect(printer(double.nan), 'n/a');
});
test('nan', () {
test('infinity', () {
final printer = HumanNumberPrinter.binary(infinity: 'huge');
expect(printer(double.infinity), 'huge');
expect(printer(double.negativeInfinity), '-huge');
});
test('precision', () {
final printer = HumanNumberPrinter.binary(precision: 1);
expect(printer(0), '0');
expect(printer(27), '27');
expect(printer(999), '999');
expect(printer(1000), '1000');
expect(printer(1023), '1023');
expect(printer(1024), '1.0 Ki');
expect(printer(1728), '1.7 Ki');
expect(printer(1855425871872), '1.7 Ti');
});
test('unitPrecision', () {
final printer =
HumanNumberPrinter.binary(precision: 2, unitPrecision: 1);
expect(printer(0), '0.0');
expect(printer(27), '27.0');
expect(printer(999), '999.0');
expect(printer(1000), '1000.0');
expect(printer(1023), '1023.0');
expect(printer(1024), '1.00 Ki');
expect(printer(1728), '1.69 Ki');
expect(printer(1855425871872), '1.69 Ti');
});
test('unitPrefix', () {
final printer = HumanNumberPrinter.binary(unitPrefix: true);
expect(printer(4), '4');
Expand Down

0 comments on commit e554d04

Please sign in to comment.