Code Monkey home page Code Monkey logo

Comments (4)

MikeMcl avatar MikeMcl commented on May 29, 2024

I'm not sure that accidental conversion to numbers is enough of a problem to introduce a breaking change, and there is no such conversion in your example, just string comparisons. The if statements would actually work okay if one or both of the operands were converted to a number, e.g. +c > b.

Have you a stronger example of where valueOf returning a string can be a problem?

If it was to be changed, I think I'd prefer it to return a number rather than throw. Or perhaps return a number if a conversion was possible, and throw on underflow to zero and overflow to Infinity.

from big.js.

alecdotninja avatar alecdotninja commented on May 29, 2024

Okay, I suppose there are two observations here:

  1. Lexical comparison of the string representations of Big.js objects is almost certainly not what a user would want if he writes a < b.
  2. In general, the conversion of a Big.js object into a native (less precise, floating point) number is probably undesirable. After all, if a user has taken the time to use this library, he presumably has deemed the native arithmetic insufficient for his needs.

I don't have another example of anything like (1) where valueOf returning a string particularly matters; however, the issue of (2) is present if any of the native number operators or Math methods are used on a Big.js object. Again, I imagine this mainly happening by mistake in process of adopting Big into an existing code-base.

As you suggested, valueOf could be defined so that it returns a number and only throws when the value cannot be precisely expressed as a native number:

Big.prototype.valueOf = function valueOf() {
  var nativeNumber = Number(this.toString());

  try {
    if(this.eq(nativeNumber.toString(10))) {
      return nativeNumber;
    }
  }catch(e){}

  throw new TypeError(this.toString() + ' cannot be represented as a native number');
};

var a = Big('1');
var b = Big('3');
var c = Big('20');

if(a < b && c > a && c > b) console.log('Comparison now works like I would intuitively expect if I mistakenly use the native comparison operators.');

+Big('34342413412348923147981237593428759345322'); // => TypeError

This would solve (1); however, it still leaves the user open to the same kind of precision loss issues that probably inspired him to start use an arbitrary precision decimal library in the first place. An overused example being:

Big('0.1') + Big('0.2'); // => 0.30000000000000004

Personally, I would rather have an exception be thrown if the interpreter tries to convert a Big.js object directly to a native number as it is almost certainly a mistake.

That being said, as you pointed out, if someone is depending on the current behavior of valueOf, this would be a breaking change. Warning users about a potential misuse of the library may not justify breaking backward compatibility.

from big.js.

MikeMcl avatar MikeMcl commented on May 29, 2024

I think it's more in keeping with JavaScript's flexible type system and the no-fuss, easy-to-use ethos of big.js that a Big number allow itself to be coerced to a primitive number when used in an arithmetic or Math operation.

You "imagine this mainly happening by mistake", but I think the contrary is more likely.

I appreciate your analysis, and agree that it would be safer and perhaps more proper to throw, but I would prefer to err on the side of being too permissive than too strict.

The original reason for valueOf returning a string rather than a number, was that only the former represents the full 'value of' a Big number.

There is also the option of adding a toNumber method, but when I considered that before, #21, I didn't think it necessary.

I'm not yet rejecting your suggestion, and I'll think about it further.

from big.js.

MikeMcl avatar MikeMcl commented on May 29, 2024

It took a while, but I've just added a strict mode in v6.0.0 which causes an error to be thrown if a primitive number is passed to the Big constructor, or if valueOf is called, or if toNumber is called on a Big which cannot be converted to a primitive number without a loss of precision.

Big.strict = false;                      // default
x = new Big(0.1); 
y = new Big('1.000000000000000000001');
y + 2;                                   // '1.0000000000000000000012'
y.toNumber();                            // 1

Big.strict = true;
x = new Big(1);                          // 'TypeError: [big.js] String expected'
y = new Big('1.000000000000000000001');
y + 2;                                   // 'Error: [big.js] valueOf disallowed'
y.toNumber();                            // 'Error: [big.js] Imprecise conversion'

Thanks for your input.

from big.js.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.