I am writing a method that must return a numeric value which is a result of an arithmetic operation applied to two input numbers.
If the operation results in an overflow then I need to use an existing big number implementation (specifically, https://github.com/MikeMcl/decimal.js/), if not then I need to return a built in Javascript Number.
Is it possible, in code, to determine that I have an overflow and I need a big number?
I think you will find it simpler to use the Big Number library from the start and then once you have the sum in the Big Number format, you can test it to see if it is small enough to fit in a regular Javascript Number and, if so, convert it to that and return that.
While this approach is slightly inefficient (involves extra conversions in some cases), it prevents you from having to predict whether the result of a math operation you haven't yet done is too big which can be kind of difficult to do and get right. Just using Big Number for the math operation guarantees that the math operation is correct and then lets you just see how big the result is and act accordingly.
If you were only doing addition or subtraction of two values, you could probably write a predictive function, but I'd be surprised if the extra effort to get this right was actually worth whatever savings there really was. Once you're doing a more complex math operation (multiple operands or multiplication or division), then you're going to need to re-implement part of the math operation in order to predict the size of the result.
For reference, my hierarchy of priorities in writing software is:
Correctness
Robustness (ability to deal with edge cases, unexpected input and any error cases)
Clarity and Maintainability of the code
Extensibility and Reusability
Performance (only when the performance is actually relevant)
Compactness
I will sacrifice some aspects of 3, 4 to improve performance, but only when I've proven that improving the performance of this particular piece of code is important to the goal of the project and only after measuring that the performance of this particular piece of code is actually the issue worth spending time on. I will never sacrifice 1 or 2 to improve performance. In your particular case, I'd look long and hard at whether the performance impact of using Big Number to do the math operation is really a problem worth sacrificing a number of other priorities for.
You could do it like this:
function multiply(a, b) {
var res = a * b;
if (isFinite(res)) {
return res;
}
return new Decimal(a).times(b);
}
multiply(2, 3); // returns number 6
multiply(2e200, 3e200); // returns BigNumber 6e+400
However, I think it may be a better idea to always return the same type of output (i.e. BigNumber), independent of the input. Right now when you use this function you always have to check what the returned result is (number or BigNumber), and act accordingly.
Related
Recently I was asked to take a binary string input 10 and NOT it so the output is 01 in Javascript. My initial thought - loop over the variables and manually flip the bits - cannot be the best solution to this problem.
I am fairly sure you can use the tilde (bitwise NOT) operator to some degree, but I am awful with bit manipulation and have struggled to do this operation properly in Javascript. How could I use tilde in this instance to invert the binary? I assume I would first convert the binary to a base ten number, invert it, and convert it back -- but is there an easy way to get it out of two's complement so my final result is still 01?
Also, this was from an interview-style question, so I'm really looking to beat out the time complexity of looping through the array - any alternative methods would also be appreciated
After ostensible testing, I have come to the conclusion that (for this particular instance) looping remains the most idiomatic, performant way to complete this binary operation. Any alternative solution was complex, and the tested op/s was negligible. Retaining a simple loop for string manipulation and memoizing remains the most performant option I tested.
In Clojurescript I am doing a minus - taking one number from another:
(let [external-take-central (- external-val central-y)
_ (log "Ans: " external-take-central " from " external-val " take " central-y)
The output from this can involve quite a lot of unnecessary decimal places:
Ans: 0.10000000000000142 from 21.1 take 21
rationalize does not exist on Clojurescript, and nor does BigDecimal.
What is the best way to deal sensibly with these floating-point arithmetic errors in the Javascript execution environment?
In this case I would like external-take-central itself to not be slightly bigger/smaller than 0.1. I would like to find a generic way to make calculations accurate and easy to reason about.
It depends on how you want to use the value. You can use available javascript libraries and functions. In general, I tend ot look at the google closure library before considering loading a separate library as you avoid issues with having to define externs etc.
One possible solution would be to use the google.string lib i.e.
(ns ....
(:require [google.string :as gstr]))
(gstr/format "%.2f" value)
or something similar should work to format your value as a string with just 2 decimal places.
EDIT: Adding some more information based on comment and to clarify some points.
Note that Clojurescript numbers are just javascript numbers and can be used in any javascript function which accepts a number. So, for example you can just do
(.round js/Math 3.00001)
or even
(.toFixed 3.0002 2)
or something more complex depending on what your requirements are. I would be wary of rounding/truncating at every calculation step. There are some cases where this might make sense (for example, you might want to restrict money calculations to 2 decimal places), but in other caes, you will just increase the amount of rounding error by doing this. For thigs like delaing with currency, I would tend to use either a clojurescript or a javascript library written for that purpose.
I have some code which requires many Math.pow() function calls per second. In testing it seems to be a very large bottleneck to the performance of the code.
The results don't need to be precise - an accuracy of anywhere upwards of 85% should done fine - but my question would be is there any way I can somehow speed these calculations up? Maybe at the cost of some precision?
Edit: these calculations are very unlikely to repeat so a cache wouldn't work.
at the cost of some precision
How much loss of precision? If you only need correct answers by a factor of 2, you could use bitwise manipulation.
function pow2(n) {
return 2 << (n-1);
}
console.log(pow2(n) === Math.pow(2, n));
The Number constructor (including number literals) use only floating point numbers. This function converts the floats to 32-bit integers as described here.
Otherwise, I doubt you'll be able to beat the optimized native implementation of Math.pow.
jsPerf is a great tool for trying multiple techniques to find the fastest one.
This could vary quite a bit by browser or operating system, but so far it turns out that Math.pow is much faster in my environment (Chrome 42, 64-bit Linux) until you open up dev tools. With dev tools open, it's slightly faster to multiply the number as many times as you need depending on the power, as in the following example:
function pow(num, pow) {
var result = num;
while (--pow) {
result *= num;
}
return result;
}
I'm running out of different ideas, but you can see what I have so far here:
http://jsperf.com/math-pow-alternatives
There is also a lot of overhead just to calling a function (hundreds of thousands of times). In this case it seems like Math.pow is the way to go, but there might be other ways to improve performance (or at least perceptible performance). If the code is blocking and the browser is experiencing some lag, you might try using web workers, or limiting the number of calculations per frame. You could also try to reduce the amount of function calls, or make sure you're interacting very minimally with the DOM (especially during the calculations, but preferably not at all).
Without a more concise code sample it will be difficult to fine-tune your code's performance.
In javascript, is there a speed advantage between the multiplication operator and the division operator? As an example...
var foo = bar * 0.01;
var foo = bar / 100;
foo is the same for both, but which statement returns the value of foo the fastest? I know this may be an incredibly small difference, however, when loop processing large amounts of data it could make a bigger difference than realized, which would then make a difference in how I construct equations to facilitate the processing.
I would say, it depends on the implementation. I would just make an own test somehow or try to google it.
For most machines, multiplications is faster, but the raw CPU speed is not decisive when it comes to scripting languages. Even when the implementation is the same, the execution time for one or the other will not differ so much, since the overhead of scripting languages is normally much bigger.
Normally the difference between different operations is so small, that it is not worth it to think about it. When you must, you probably are using the wrong language, anyhow.
In computer systems, the only basic operators are + (adders) and (*) multipliers. You either add (negative or positive) numbers or rotate numbers (either left or right for multiplication and division respectively). You should be able to work it out whether multiplication or division takes longer...
*btw...unless I am wrong, your question has nothing to do with javascript. Javascript is an interpreted language with engines such as spidermonkey or rhino....
FYI You should read this - directly from the main people....to have better insight of "what" might be happening.
I always assumed that booleans were more efficient than ints at storing an on/off value - considering that's their reason for existence. I recently decided to check if this is true with the help of jsperf, and it came up with some contrary results!
http://jsperf.com/bool-vs-int
Here is the first test I tried. Toggling the value of the on/off switch. On Chrome it's significantly faster to do this using 1/0, but on firefox it's slightly faster to do this using bool. Interesting.
http://jsperf.com/bool-vs-int-2
And here's the second test I tried. Using them in a conditional. This appears to have significant advantage for ints as opposed to bools, up to 70% faster to use 1/0 instead of booleans - on both firefox and chrome. Wtf?
I guess my question is, am I doing something wrong? Why are ints so much better at boolean's job? Is the only value of using bools clarity, or am I missing something important?
Disclaimer, I can only speak for Firefox, but I guess Chrome is similar.
First example (http://jsperf.com/bool-vs-int):
The Not operation
JägerMonkey (Spidmonkey's JavaScript methodjit) inlines the check for boolean first and then just xors, which is really fast (We don't know the type of a/b, so we need to check the type).
The second check is for int, so if a/b would be a int this would be a little bit slower.
Code
The Subtract operation.
We again don't know the type of c/d. And again you are lucky we are going to assume ints and inline that first. But because in JavaScript number operations are specified to be IEEE 754 doubles, we need to check for overflow. So the only difference is "sub" and a "conditional jump" on overflow vs. plain xor in case 1.
Code
Second example:
(I am not 100% sure about these, because I never really looked at this code before)
and 3. The If.
We inline a check for boolean, all other cases end up calling a function converting the value to a boolean.
Code
The Compare and If.
This one is a really complex case from the implementation point of view, because it was really important to optimize equality operations. So I think I found the right code, that seems to suggest we first check for double and then for integers.
And because we know that the result of a compare is always a boolean, we can optimize the if statement.
Code
Followup I dumped the generated machine code, so if you are still interested, here you go.
Overall this is just a piece in a bigger picture. If we knew what kind of type the variables had and knew that the subtraction won't overflow then we could make all these cases about equally fast.
These efforts are being made with IonMonkey or v8's Crankshaft. This means you should avoid optimizing based of this information, because:
it's already pretty fast
the engine developers take care of optimizing it for you
it will be even faster in the future.
your test was a bit off due to the definition of "function" and "var" and the call for the function. The cost to define function and variables and calling them will differ from engine to engine. I modified your tests, try to re-run with your browsers (note that IE was off because the first run was weird but consecutive runs were as expected where bool is fastest): http://jsperf.com/bool-vs-int-2/4
I don't know but in the second test it does
if(a) bluh();
vs
if(c == 1) bluh();
maybe c==1 is faster because you're comparing a value with one with the same type
but if you do if(a) then js need to check if the value evaluates to true, not just if it is true...
That could be the reason...
Maybe we need to test
if(c==1)
vs
if(a===true) with three =
For me the choice would be based on API usage. Always return that which is most useful. If I use secondary code, I'd favor methods that return booleans. This probably makes the code ready to be chained. The alternative is to provide overloaded methods.
Diggin' deep here. Regarding performance, I'm still unsure (this is why I found this thread) if booleans vs 0/1 is faster when computing and it still seems heavily browser-dependent. But take into account, that in extremely huge datasets the data has to be downloaded by the user first anyway:
"true" and "false" obv take up 4 or 5 characters respectively, whereas 0 and 1 are only 1 character. So it might save you a little bit of bandwidth at least, so less time to load and only after that is it up to the client's browser and hardware how to deal with those types, which seems pretty much negligible.
As a little bonus and to actually contribute something, since (I think?) no one mentioned it here, if you are going with the 0 and 1 approach, instead of using if-statements you can use bitwise operations to toggle between them, which should be pretty fast:
x=0;
x^=1; // 1
x^=1; // 0
This is the equivalence to using this toggle for booleans:
x=false;
x=!x; // true
x=!x; // false