E3F2 Conversion bug for values < 1 with cutOffNumber 0 · Issue #346 · convert-units/convert-units · GitHub
[go: up one dir, main page]

Skip to content

Conversion bug for values < 1 with cutOffNumber 0 #346

@mkusold

Description

@mkusold

I am running into a bug. I have 0.001 inches and the toBest option is converting to miles.
I read through the source code and I think there's an edge case for values that are -1 < x < 1 such as 0.001 that causes the toBest to find the highest specificty of units (miles) instead of the lowest most relevant unit (inches) specifically when cutOffNumber is 0

import convert from 'convert-units'; //  "convert-units": "^2.3.4"

function main(){
  const LESS_THEN_1_VAL = 0.001;
  const FROM_UNIT = "in";
  const converted = convert(LESS_THEN_1_VAL).from(FROM_UNIT).toBest({
    cutOffNumber: 0,
  });
  // OUTPUT:
  // converted {
  //   val: 1.5782828282828283e-8,
  //   unit: 'mi',
  //   singular: 'Mile',
  //   plural: 'Miles'
  // }
  // expected to be whatever the most specific imperial unit is available is (such as 'in' or 'mil')
  console.log("converted", converted)
}
main();

Here is how I'm working around this in my codebase:

export const getCustomBest = (
  value: number,
  fromUnits: ConvertUnits,
  toSystem: MeasurementSystem
): BestResult | null => {
  const system =
    convert().describe(fromUnits).system === MeasurementSystem.si
      ? undefined
      : toSystem;
  // try to get best using the standard convert lib
  let converted = convert(value)
    .from(fromUnits)
    .toBest({
      system,
      exclude: EXCLUDED_UNITS,
      cutOffNumber: value < 0 ? -1 : 1,
    });
  // handle -> -1 < x < 1
  if (!converted) {
    const conversionOptions: AnchoredBestResult[] = [];
    const possibilities = convert()
      .from(fromUnits)
      .possibilities()
      .filter((p) => !EXCLUDED_UNITS.includes(p));
    for (const possibility of possibilities) {
      const unit = convert().describe(possibility);
      const unitDetails = convert().getUnit(possibility);
      if (!unitDetails) {
        continue;
      }
      if (unit.system === system) {
        const result = convert(value).from(fromUnits).to(possibility);
        conversionOptions.push({
          val: result,
          unit: possibility,
          singular: unit.singular,
          plural: unit.plural,
          to_anchor: unitDetails.unit.to_anchor,
        });
      }
    }
    // pick the largest from the options -- if there are absolutely no options then return null
    if (conversionOptions.length > 0) {
      let best: AnchoredBestResult | null = null;
      for (const option of conversionOptions) {
        if (best
5ADE
 === null || option.to_anchor < best.to_anchor) {
          best = option;
        }
      }
      converted = best;
    }
  }
  return converted;
};

PS thanks for making this lib! It's much appreciated!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      0