Let me be brief. I'm trying to calculate
alert((Math.pow(7,35))%71)
but it gives me 61, when the result must be 70. What's wrong?
As others mentioned before with regards to using Math.pow(7,35), this resulting number is way too big for Javascript to handle.
To resolve your problem you need to use an external javascript library.
(Or write your own ;) )
Here are some examples of Javascript libraries that handle big numbers.
BigNum
Bignumber
I hope it helps.
The number you're using is too big for javascript. The max size of an int is 2^53 -- which is less than 7^35.
The only value which requires more precision is an intermediate result. So the problem can also be avoided without the need for higher precision variables when you have an algorithm that doesn't need the problematic intermediate result.
The following formula can be useful for that:
(a.b) % c = (a % c)(b % c) % c
This means Math.pow(7,35)%71 = ((Math.pow(7,17)%71) * (Math.pow(7,18)%71)) % 71.
Now the intermediate results are smaller, but might still be too big. So we need to split up further and to apply the modula operator on smaller intermediate results.
So you can do something like this:
Math.pow((Math.pow(7,7)%71),5)%71
But you probably need to do this for integer numbers wich are variable (otherwise, you could have avoided the problem by hardcoding the result).
So, you need to have an idea about the range of values you can expect and to define an algoritm that splits up the power calculation into pieces that will always have results that are small enough when the input is within the expected range.
And whatever you choose for a calculation like this, calculation with higher precision variables (using a specialized library) or a specilized algoritm, you should always assert the input to make sure your calculation returns a value only when you are sure it can deliver a correct value. Otherwise your implementation becomes unreliable for anyone who isn't aware of the range in which it is valid. Otherwise return an exception with a message that tells clearly which input or combination of inputs is the problem and why.
Related
I'm dealing with relatively small and simple numbers. I first tried to do the rounding (2 signs after digit) with infamous toFixed. It's a known issue: sometimes it works incorrectly. But what struck me is the fact that it also works inconsistently:
(0.395).toFixed(2); // "0.40"
(0.295).toFixed(2); // "0.29"
These numbers are very similar, 3 signs after digit and yet different behavior.
So, I decided to switch to using Math.round. Shortly, I encountered another problem:
Math.round(0.35055 * 10000) / 100; // produces 35.05 instead of 35.06
Is Math.round also problematic? Then, what method should be used?
Unfortunately JavaScript is known to have such precision issues, issues that are better explained in the following question: Is floating point math broken?, as pointed in the comments.
If you require a greater degree of numerical accuracy, I would suggest you to use a library such as BigNumber, which also comes with its own toFixed method.
Your example would look something like this:
var a = new BigNumber('0.35055');
a = a.times(10000)
a = a.dividedBy(100)
console.log(a.toFixed(2)); //would log "35.06"
For brevity you can also chain the operations, like this: a.times(10000).dividedBy(100).toFixed(2)
I think this is working as designed. Keep in mind these numbers are stored in base 2, so there is a loss of precision when converting to and from base 10. And you have to look at these conversions if you want to understand why it looks inconsistent. If you have a fixed number of decimals that you want to keep precisely, you can use integers for operations and convert only for display.
I've tried big.js, bignumber.js, and decimal.js; they all work reasonably well up to a certain point, but fall short when I need to do arbitrary-precision calculations with large enough numbers of "odd" digits (my current test case is 31435517643980 * (1 / 31435517643980) === 1). I am open to any solution that allows me to process expressions like this, including calls to an external API. I'm currently looking at Wolfram|Alpha's API, but the 2000 calls/month limit is a restriction I'd like to avoid, because my application is going to be making quite a few calls.
If this is the wrong SE site for this question, please let me know and/or move it.
Possibly the most common way to do this is simply multiply both numbers by the same multiplier to make them have no decimals, and then do the operation, then divide again. Here's a crude implementation:
function getDigits(n){
return n.toString().substring(n.toString().indexOf('.')+1).length;
}
function xNums(n1,n2){
var highRes=(n1*Math.pow(10,getDigits(n1))*(n2*Math.pow(10,getDigits(n2))));
return highRes/Math.pow(10,getDigits(n1))/Math.pow(10,getDigits(n2));
}
Then, run xNums(31435517643980,(1 / 31435517643980))===1. Works for me in Chrome
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 8 years ago.
Improve this question
Given values for the variables s, v, and h, and given a library such as numeric.js how can I numerically solve the following equation for a within a given degree of accuracy?
I'm wanting a JS algorithm for use in-browser.
Separating variables and parameters
You could start by substituting b = a/h. That would turn your equation into
2b*sinh(1/(2b)) = sqrt(s²-v²)/h
That way you have all the inputs on the right hand side, and the variable on the left hand side, but unfortunately still occuring in several places in a transcendental form. The benefit is that we can now treat the right-hand side as a single number in order to gain some understanding of this function.
First look at a plot
The function seems reasonably well-behaved:
So you can do standard numerical root-finding methods, e.g. Newton's method, to find the position where this function takes a given value (i.e. the one you computed from the right-hand side). If you interpret root-finding as finding locations where a function is zero, then the function for which you want to find zeros is the difference, i.e.
2a*sinh(h/(2a)) - sqrt(s²-v²)
Using optimization from numeric.js
If you want to make use of numeric.js, numeric.uncmin would likely be your best bet. At least it's the best I could find in the docs so far. (Perhaps there is some bare root-finding implementation in there, but if so, I couldn't find it yet.) You'd try to find the minimum of the function
(2a*sinh(h/(2a)) - sqrt(s²-v²))²
interpreted as a function of a, and hope that that minimum is actually (close to) zero. You might get better results (i.e. faster convergence and/or lower error) by also providing the gradient (derivative) of that function as a separate argument. You can use Wolfram Alpha to find that derivative.
Further rewriting of the function
Let's define f as f(b) = 2b*sinh(1/(2b)). You are trying to find out at what position f assumes a given value. In order to make convergence faster, you can try to turn this f into a different function which will be close to linear. Toying around with plots, I've come up with this:
g(b) = (f(b) - 1)^(-1/2)
You can apply the same conversion to the right hand side to see the desired value for this function. For b > 0.06 this looks fairly linear, so it should converge really fast. Provided your parameters are expected to be in that range where it is almost linear, but even for smaller b it should be no worse than the original formulation. You could use the linear form to compute the starting position of your Newton's method, but I wouldn't bother: as long as you start with a reasonably big value, the first step of Newton's method will do just that.
this is transcendent equation
I assume real domain in that case you can not separate the unknown from it (in general) instead you still can solve it numerically (as you intended)
I am too lazy to do proper analysis of 2a.sinh(h/2a)=sqrt(s.s-v.v)
but if I see it right then 2a.sinh(h/2a) is monotone so let c=sqrt(s.s-v.v) for simplicity and speed up. As I see it c >= 0 so if h >= 0 then a = <0,+inf)
find value crossing
double a0,a1,da=initial accuracy step;
for (a1=0.0;2a.sinh(h/2a)<=sqrt(s.s-v.v);a1+=da);
now a1 holds approximate top bound solution
for (a0=a1;2a.sinh(h/2a)>sqrt(s.s-v.v);a0-=da);
now a0 holds approximate low bound solution
find solution in desired accuracy
if a0==a1 then you have found exact solution so stop
if fabs(a1-a0)<=accuracy you are inside your accuracy so stop and lower the da for example da*=0.01; this will boost accuracy 100 times. Now search for solution again but only on interval <a0,a1> and repeat this until solution is found
[notes]
Another example of solution of transcendent equation is here: solving Kepler`s equation. When nothing else works you still can try this:
How approximation search works
I'm tried to make some world generation mechanism using Math.random() whenever I needed something random, but then decided that I wanted it seed-based, so, given a seed, I changed all of the Math.random() to Math.sin(seed++)/2+0.5, hoping it would do the same thing, but would be the same if the seed was the same seed.
Then someone made me notice that the sin wave hasn't got even distribution, and finally I saw why some of my code was working strangely.
I was wondering if there was a simple fix, or if there isn't, another very simple seed based randomizer like this
So, I looked at your method, t1wc, and I found that it isn't actually evenly distributed. It is significantly more likely to spit out numbers near 0 or near 1 than it is to spit out numbers near 0.5, for example. This is just a consequence of the way that the sine function works.
Instead, you might try using a method called Blum Blum Shub (named after the authors of the original paper, wonderfully). It is evenly distributed and quite fast. Given a seed, it works as follows:
Square the seed and put the result in a temporary variable (x).
Take the mod of x base M.
M is a product of two large primes.
The value of x is a new seed to be used for future calculations.
Return x/M as your pseudo-random number. It will be evenly distributed between 0 and 1.
Below is a simple implementation of a Blum Blum Shub:
var SeededRand = function(seed, mod1, mod2)
{
return function()
{
seed = (seed*seed) % (mod1*mod2);
return seed/(mod1*mod2);
};
};
If you want to make a new random number generator, you just call:
var rand = SeededRand(seed, mod1, mod2);
Where seed is some initial seed (1234567890 works well), and mod1 and mod2 are some large primes (7247 and 7823 work well). rand is just a variable that I've defined to hold the output.
Now, to start getting random values, you just call:
rand();
Which will spit out a different value each time you run it.
If you have any questions, please ask!
There is a very nice seed-based randomizing script already made. It can be found here.
ok guys, found out this is what I'm really looking for:
(((Math.sin(seed.value++)/2+0.5)*10000)%100)/100
It sends out even spreaded numbers, and I guess it's a lot simpler than any other number generator I've seen
Is this correct? using - http://en.wikipedia.org/wiki/Binomial_probability
Looks like values are from .0000000000000000 to .9999999999999999
Probability of happening twice = p^2 = (1/9999999999999999)^2 = 1.0 e-32
I think I am missing something here?
Also, how does being a pseudo random number generator change this calculation?
Thank You.
In an ideal world Math.random() would be absolutely random, with one output being completely independent from another, which (assuming p=the probability of any given number being produced) results in a probably of p^2 for any value being repeated immediately after another (as others have already said).
In practice people want Math.random to be fast which means pseudo-random number generators are used by the engines. There are many different kinds of PRNG but the most basic is a linear congruential generator, which is basically a function along the lines of:
s(n + 1) = some_prime * s(n) + some_value mod some_other_prime
If such a generator is used then you won't see a value repeated until you've called random() some_other_prime times. You're guaranteed of that.
Relatively recently however it's become apparent that this kind of behaviour (coupled with seeding the PRNGs with the current time) could be used for some forms tracking have led to browsers doing a number of things that mean you can't assume anything about subsequent random() calls.
I think the probability of getting two numbers in a row is 1 divided by the range of the generator, assuming that it has a good distribution.
The reason for this is that the first number can be anything, and the second number needs to just be that number again, which means we don't care about the first number at all. The probability of getting the same number twice in a row is the same as the probability of getting any particular number once.
Getting some particular number twice in a row, e.g. two 0.5s in a row, would be p^2; however, if you just care about any number twice in a row, it's just p.
If the numbers were truly random, you'd expect them, indeed, to appear with probability 1/p, so twice that would be 1/p^2.
The value for p is not exactly the one you have though, because the numbers are being represented internally as binary. Figure out how many bits of mantissa the numbers have in javascript and use that for your combinatoric count.
The "pseudorandom" part is more interesting, because the properties of pseudorandom number generators vary. Knuth does some lovely work with that in Seminumerical Algorithms, but basically most usual PN generators have at least some spectral distributiuon. Cryptograp0hic PN generators are generally stronger.
Update: The amount of time shouldn't be significant. Whether it's a millisecond or a year, as long as you don't update the state The probabilities will stay the same.
The probability that you would get 2 given numbers is (1/p)^2, but the probability that you get 2 of same numbers (any) is 1/p. That is because the first number can be anything, and the second just needs to match that.
You can kind of find out, just let it run a few days :)
var last = 0.1;
var count = 0 | 0;
function rand(){
++count;
var num = Math.random();
if(num === last){
console.log('count: '+count+' num: '+num);
}
last = num;
}
while(true) rand();