Merge remote-tracking branch 'origin/develop' into develop

This commit is contained in:
Jos de Jong 2023-04-03 13:55:06 +02:00
commit d9cf344e5a
8 changed files with 76 additions and 10 deletions

View File

@ -203,6 +203,26 @@ math.createUnit('θ', '1 rad')
math.evaluate('1θ + 3 deg').toNumber('deg') // 60.29577951308232
```
## Numeric type of the value of a unit
The built-in units are always created with a value being a `number`. To turn the value into for example a `BigNumber` or `Fraction`, you can convert the value using the function `math.fraction` and `math.bignumber`:
```js
math.unit(math.fraction(10), 'inch').toNumeric('cm') // Fraction 127/5
math.fraction(math.unit(10, 'inch')).toNumeric('cm') // Fraction 127/5
math.bignumber(math.unit(10, 'inch')).toNumeric('cm') // BigNumber 25.4
math.unit(math.bignumber(10), 'inch').toNumeric('cm') // BigNumber 25.4
```
When using the expression parser, it is possible to configure numeric values to be parsed as `Fraction` or `BigNumber`:
```js
math.config({ number: 'Fraction' })
math.evaluate('10 inch').toNumeric('cm') // Fraction 127/5
```
## API
A `Unit` object contains the following functions:

View File

@ -65,6 +65,12 @@ export const createBignumber = /* #__PURE__ */ factory(name, dependencies, ({ ty
return x
},
Unit: typed.referToSelf(self => (x) => {
const clone = x.clone()
clone.value = self(x.value)
return clone
}),
Fraction: function (x) {
return new BigNumber(x.n).div(x.d).times(x.s)
},

View File

@ -37,7 +37,7 @@ export const createFraction = /* #__PURE__ */ factory(name, dependencies, ({ typ
*
* bignumber, number, string, unit
*
* @param {number | string | Fraction | BigNumber | Array | Matrix} [args]
* @param {number | string | Fraction | BigNumber | Unit | Array | Matrix} [args]
* Arguments specifying the value, or numerator and denominator of
* the fraction
* @return {Fraction | Array | Matrix} Returns a fraction
@ -71,6 +71,12 @@ export const createFraction = /* #__PURE__ */ factory(name, dependencies, ({ typ
return x // fractions are immutable
},
Unit: typed.referToSelf(self => (x) => {
const clone = x.clone()
clone.value = self(x.value)
return clone
}),
Object: function (x) {
return new Fraction(x)
},

View File

@ -116,9 +116,11 @@ export const createNumber = /* #__PURE__ */ factory(name, dependencies, ({ typed
return x.valueOf()
},
Unit: function (x) {
throw new Error('Second argument with valueless unit expected')
},
Unit: typed.referToSelf(self => (x) => {
const clone = x.clone()
clone.value = self(x.value)
return clone
}),
null: function (x) {
return 0

View File

@ -71,6 +71,20 @@ describe('bignumber', function () {
assert.strictEqual(b.toString(), '0.6666666666666666666666666666666666666666666666666666666666666667')
})
it('should convert the number value of a Unit to BigNumber', function () {
const b = math.bignumber(math.unit(10, 'inch')).toNumeric('cm')
assert.ok(b instanceof BigNumber)
assert.strictEqual(b.valueOf(), '25.4')
})
it('should convert the Fraction value of a Unit to BigNumber', function () {
const b = math.bignumber(math.unit(math.fraction(1, 2), 'cm')).toNumeric('cm')
assert.ok(b instanceof BigNumber)
assert.strictEqual(b.valueOf(), '0.5')
})
it('should apply precision setting to bignumbers', function () {
const mymath = math.create({
precision: 32

View File

@ -11,6 +11,10 @@ describe('fraction', function () {
equalFraction(math.fraction(null), new Fraction(0))
})
it('should create a fraction from an irrational number', function () {
equalFraction(math.fraction(math.pi), new Fraction(11985110, 3814979))
})
it('should fail to create a fraction in case of non-integer quotient', function () {
assert.throws(() => math.fraction(4, 5.1), /Parameters must be integer/)
assert.throws(() => math.fraction(62.8, 10), /Parameters must be integer/)
@ -28,6 +32,16 @@ describe('fraction', function () {
equalFraction(f, new Fraction('0.6666666666666666666666666666666666666666666666666666666666666667'))
})
it('should convert the number value of a Unit to Fraction', function () {
equalFraction(math.fraction(math.unit(0.5, 'cm')).toNumeric('cm'), new Fraction(1, 2))
equalFraction(math.fraction(math.unit(10, 'inch')).toNumeric('cm'), new Fraction(127, 5))
})
it('should convert the BigNumber value of a Unit to Fraction', function () {
equalFraction(math.fraction(math.unit(math.bignumber(0.5), 'cm')).toNumeric('cm'), new Fraction(1, 2))
equalFraction(math.fraction(math.unit(math.bignumber(10), 'inch')).toNumeric('cm'), new Fraction(127, 5))
})
it('should clone a fraction', function () {
const a = math.fraction(1, 3)
const b = math.fraction(a)

View File

@ -35,6 +35,11 @@ describe('number', function () {
approx.equal(number(math.unit('52cm'), 'm'), 0.52)
})
it('should convert the value of a unit to a number', function () {
const value = number(math.unit(math.bignumber(52), 'cm'))
assert.strictEqual(value.toNumeric('cm'), 52)
})
it('should parse the string if called with a valid string', function () {
approx.equal(number('2.1e3'), 2100)
approx.equal(number(' 2.1e-3 '), 0.0021)
@ -64,7 +69,6 @@ describe('number', function () {
})
it('should throw an error with wrong type of arguments', function () {
assert.throws(function () { number(math.unit('5cm')) }, /Second argument with valueless unit expected/)
// assert.throws(function () {number(math.unit('5cm'), 2)}, TypeError); // FIXME: this should also throw an error
assert.throws(function () { number(math.unit('5cm'), new Date()) }, TypeError)
assert.throws(function () { number('23', 2) }, TypeError)

10
types/index.d.ts vendored
View File

@ -585,7 +585,7 @@ declare namespace math {
* @returns The created bignumber
*/
bignumber(
x?: number | string | Fraction | BigNumber | boolean | Fraction | null
x?: number | string | Fraction | BigNumber | Unit | boolean | null
): BigNumber
bignumber<T extends MathCollection>(x: T): T
@ -664,12 +664,12 @@ declare namespace math {
/**
* Create a fraction convert a value to a fraction.
* @param args Arguments specifying the numerator and denominator of the
* @param value Arguments specifying the numerator and denominator of the
* fraction
* @returns Returns a fraction
*/
fraction(
value: number | string | BigNumber | Fraction | FractionDefinition
value: number | string | BigNumber | Unit | Fraction | FractionDefinition
): Fraction
fraction(values: MathCollection): MathCollection
/**
@ -4148,7 +4148,7 @@ declare namespace math {
*/
bignumber(
this: MathJsChain<
number | string | Fraction | BigNumber | boolean | Fraction | null
number | string | Fraction | BigNumber | Unit | boolean | null
>
): MathJsChain<BigNumber>
bignumber<T extends MathCollection>(this: MathJsChain<T>): MathJsChain<T>
@ -4214,7 +4214,7 @@ declare namespace math {
*/
fraction(
this: MathJsChain<
number | string | BigNumber | Fraction | FractionDefinition
number | string | BigNumber | Unit | Fraction | FractionDefinition
>,
denominator?: number
): MathJsChain<Fraction>