Skip to content

Commit

Permalink
Changed value of divide by zero to non-a-number; defined not-a-number…
Browse files Browse the repository at this point in the history
… literal.
  • Loading branch information
amyjko committed Jul 13, 2024
1 parent daa664e commit 3497f36
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 42 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ Dates are in `YYYY-MM-DD` format and versions are in [semantic versioning](http:
- Permit comma separators between text literals, docs, and names, allowing line breaks for text.
- Define `Input`s corresponding definition to enable code localization.
- Improved `MissingInput` conflict.
- Changed value of divide by zero to non-a-number; defined not-a-number literal.

## 0.10.4 2024-07-08

Expand Down
2 changes: 1 addition & 1 deletion src/parser/Tokenizer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ test.each([
['1,0', '1,0|'],
['0.5', '0.5|'],
['.5', '.5|'],
['0∞π', '0|∞|π|'],
['0∞π!#', '0|∞|π|!#|'],
['🌏🌍🌎', '🌏|🌍|🌎|'],
[
'一 十 百 百一 百四十五 百九十九 千一 万十一 万',
Expand Down
1 change: 1 addition & 0 deletions src/parser/Tokenizer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ const CodeTokenPatterns: TokenPattern[] = [
{ pattern: CONVERT_SYMBOL3, types: [Sym.Convert] },
{ pattern: NONE_SYMBOL, types: [Sym.None, Sym.None] },
{ pattern: TYPE_SYMBOL, types: [Sym.Type, Sym.TypeOperator] },
{ pattern: /^!#/, types: [Sym.Number] },
{ pattern: LITERAL_SYMBOL, types: [Sym.Literal] },
{
pattern: OR_SYMBOL,
Expand Down
2 changes: 1 addition & 1 deletion src/values/NumberValue.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ test.each([
['1 · 0', '0'],
['1 ÷ 1', '1'],
['0 ÷ 1', '0'],
['1 ÷ 0', 'ø'],
['1 ÷ 0', '!#'],
['10 ÷ 5', '2'],
['-10 ÷ -5', '2'],
['1 ÷ 3', '0.33333333333333333333'],
Expand Down
82 changes: 42 additions & 40 deletions src/values/NumberValue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export default class NumberValue extends SimpleValue {
creator: Expression,
number: number | Token | Decimal | string,
unit?: Unit,
precision?: number
precision?: number,
) {
super(creator);

Expand Down Expand Up @@ -68,8 +68,10 @@ export default class NumberValue extends SimpleValue {
const negated = text.charAt(0) === '-';
if (negated) text = text.substring(1);

// Not a number
if (text === '!#') return [new Decimal(NaN), undefined];
// Infinity
if (number.isSymbol(Sym.Infinity) || text === '∞') {
else if (number.isSymbol(Sym.Infinity) || text === '∞') {
return [new Decimal(Infinity * (negated ? -1 : 1)), undefined];
}
// Pi
Expand Down Expand Up @@ -126,7 +128,7 @@ export default class NumberValue extends SimpleValue {
return new NumberValue(
requestor,
this.num.pow(new Decimal(1).div(operand.num)),
this.unit.root(operand.num.toNumber())
this.unit.root(operand.num.toNumber()),
);
}

Expand Down Expand Up @@ -154,33 +156,33 @@ export default class NumberValue extends SimpleValue {
return new NumberValue(
requestor,
this.num.times(operand.num),
this.unit.product(operand.unit)
this.unit.product(operand.unit),
);
}

divide(
requestor: Expression,
divisor: NumberValue
divisor: NumberValue,
): NumberValue | NoneValue {
return divisor.num.isZero()
? new NoneValue(requestor)
? new NumberValue(requestor, new Decimal(NaN))
: new NumberValue(
requestor,
this.num.dividedBy(divisor.num),
this.unit.quotient(divisor.unit)
this.unit.quotient(divisor.unit),
);
}

remainder(
requestor: Expression,
divisor: NumberValue
divisor: NumberValue,
): NumberValue | NoneValue {
return divisor.num.isZero()
? new NoneValue(requestor)
: new NumberValue(
requestor,
this.num.modulo(divisor.num),
this.unit
this.unit,
);
}

Expand All @@ -204,22 +206,22 @@ export default class NumberValue extends SimpleValue {
return new BoolValue(
requestor,
this.num.greaterThan(operand.num) &&
this.unit.isEqualTo(operand.unit)
this.unit.isEqualTo(operand.unit),
);
}

lessThan(requestor: Expression, operand: NumberValue): BoolValue {
return new BoolValue(
requestor,
this.num.lessThan(operand.num) && this.unit.isEqualTo(operand.unit)
this.num.lessThan(operand.num) && this.unit.isEqualTo(operand.unit),
);
}

power(requestor: Expression, operand: NumberValue) {
return new NumberValue(
requestor,
this.num.pow(operand.num),
this.unit.power(operand.num.toNumber())
this.unit.power(operand.num.toNumber()),
);
}

Expand Down Expand Up @@ -248,15 +250,15 @@ export default class NumberValue extends SimpleValue {
this.num.isNaN()
? '!#'
: !this.num.isFinite()
? `${this.num.isPositive() ? '' : '-'}∞`
: this.num.toString()
? `${this.num.isPositive() ? '' : '-'}∞`
: this.num.toString()
}${this.unit.toString()}`;
}

getDescription(concretize: Concretizer, locales: Locales) {
return concretize(
locales,
locales.get((l) => l.term.number)
locales.get((l) => l.term.number),
);
}

Expand Down Expand Up @@ -322,7 +324,7 @@ function convertBase(text: string, negated: boolean): NumberAndPrecision {
while (text.indexOf('_') >= 0)
text = text.replace(
'_',
Decimal.random().times(base).floor().toString()
Decimal.random().times(base).floor().toString(),
);

const [integral, fractional] = text.split('.');
Expand All @@ -332,16 +334,16 @@ function convertBase(text: string, negated: boolean): NumberAndPrecision {
d === 'A'
? 10
: d === 'B'
? 11
: d === 'C'
? 12
: d === 'D'
? 13
: d === 'E'
? 14
: d === 'F'
? 15
: parseInt(d)
? 11
: d === 'C'
? 12
: d === 'D'
? 13
: d === 'E'
? 14
: d === 'F'
? 15
: parseInt(d),
);
if (integralDigits.find((d) => d >= base) !== undefined) {
return [new Decimal(NaN), undefined];
Expand All @@ -352,8 +354,8 @@ function convertBase(text: string, negated: boolean): NumberAndPrecision {
const digit = integralDigits.pop() as number;
num = num.plus(
new Decimal(digit).times(
new Decimal(base).pow(new Decimal(position))
)
new Decimal(base).pow(new Decimal(position)),
),
);
position++;
}
Expand All @@ -366,23 +368,23 @@ function convertBase(text: string, negated: boolean): NumberAndPrecision {
d === 'A'
? 10
: d === 'B'
? 11
: d === 'C'
? 12
: d === 'D'
? 13
: d === 'E'
? 14
: d === 'F'
? 15
: parseInt(d)
? 11
: d === 'C'
? 12
: d === 'D'
? 13
: d === 'E'
? 14
: d === 'F'
? 15
: parseInt(d),
);
while (fractionalDigits.length > 0) {
const digit = fractionalDigits.shift() as number;
num = num.plus(
new Decimal(digit).times(
new Decimal(base).pow(new Decimal(position).neg())
)
new Decimal(base).pow(new Decimal(position).neg()),
),
);
position++;
}
Expand Down

0 comments on commit 3497f36

Please sign in to comment.