Javascript: Can Math.PI survive a calculation? - javascript

Let's say I want to calculate with Pi and the result would "contain" Pi as well if I do the calculation on the paper.
Is there any way I can tell Javascript to calculate with Pi and maintain it?
From my recent view, this is not possible as computer systems are limited. I assume you need something like "symbolic calculation" plus a parser. But maybe I am wrong and there is another way.
I also thought of setting PI after calculation using value/Math.PI and in case this is very close to an integer, output "pi" instead. But well, this is no clean solution.
For clarification: Instead of a digit I want to output Pi. And it should be ensured that it is really Pi (by calculation).

I may be misunderstanding the question here so please correct me if I am, but based on the link in the comments, you have:
Umfang: 9,425 u = 2·π·r
Flächeninhalt: 7,069 AK = π·r2
You can't just "do the calculation with pi", but if you want to output π, go about it the other way: you can calculate without it, treating it as an unknown, and just append it to the result as a string:
Umfang: 3π u = 2·π·r (result = (2 * r) + "π")
Flächeninhalt: 2.25π AK = π·r2 (result = (r * r) + "π")

Related

Efficiently sorting large arrays of people by their proximity to the user

So I'm trying to create a list of the 15 closest people in an array of varying sizes. The array will almost always be ~100 objects in size, but for the sake of testing, I'm trying to make it work with 10,000 (there may be need for the project to be scaled up to these numbers further down the line).
Currently, the method in place is to loop through the array of people, and calculate their proximity to the user based on both the person in question's and the user's latitude and longitude (the former of which is stored in the array). This is done using the haversine formulae and works well (though it does take ~500 milliseconds).
The problem however is that when run on a mobile device (a Samsung Galaxy S5 for the sake of this example), performance really suffers. The time taken for the S5 to sort through 10,000 records in order of how close they are to a pre-determined latitude and longitude is a staggering 1,500-1,600 milliseconds, an unacceptable delay for an app that will be doing many things either side of this process.
So my question is, am I missing some fundamentally more efficient means of sorting this list? Is there an alternative formulae available that is more efficient? Could I simply calculate the combined difference in Latitude and Longitude in .000001s and sort based on that?
Notes:
The user's location is variable, so proximities cannot be stored
I am aware that I'm asking a mobile CPU to perform 100,000,000 calculations in a short space of time and so this may be unavoidable
The method of sorting is the native JavaScript sort method, below is a simplified version of what I am doing to test these timings:
patientArray.sort(function(a, b)
{
return GetDistanceToPoint(a["Lat"], a["Lng"]) - GetDistanceToPoint(b["Lat"], b["Lng"]);
});
// Function to get the User's distance to a point
function GetDistanceToPoint(Latitude, Longitude)
{
// Check if the User's current Latitude and Longitude are available
if(currentLat && currentLng)
{
// Convert degrees to a radius
function degreeToRadius(degree)
{
return degree * (Math.PI/180)
}
// Variable to store radius of the Earth in Km
var earthRadius = 6371;
// Calculate the distance between the two points
var dLat = degreeToRadius(Latitude-currentLat);
var dLon = degreeToRadius(Longitude-currentLng);
var a = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.cos(degreeToRadius(currentLat)) * Math.cos(degreeToRadius(Latitude)) * Math.sin(dLon/2) * Math.sin(dLon/2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
var d = earthRadius * c;
return d;
}
return "-1";
}
It all has to be tested but here are some ideas that I would try.
For heavy use of trigonometric functions you can use lookup tables. This is always a good idea. For example precompute 360 (or more) values of sin() and for every sin(radians) in your code use sinTable[degrees].
(I say 360 values as an example because with that your index is an angle in degrees but any value will do and it all depends on what precision you need - it can have thousands of values if needed.)
Avoid unnecessary calculations. May seem obvious but people often write something like x/(2*Math.PI) instead of x*A where A (a better name of course) is computed once as 1/(2*Math.PI).
Memoize every value that you can, if it makes sense.
If your data have some specific qualities, like for example never spanning half of the planet, then you can try to cheat a little bit and use coordinates on a flat plane - then you only have to compute square roots (which could also be precomputed to use lookup tables).
Those are the first things that crossed my mind. Hope it helps.
UPDATE:
You made an edit so I know a little bit more now. Here are my tips:
Don't convert degrees to radians. Keep degrees and use them as indexes in lookup tables of precomputed values of trigonometric functions. If you need more precision then multiply the degrees by 10 or something and use a scale from 0 to 3600 instead of 0 to 360. Find a good size/precision compromise that works for you.
You can eliminate all sin() and cos() calls that way and if you're lucky you can eliminate atan2(). I wouldn't worry so much about sqrt() but you can eliminate it too if you know what the values are typically going to be. If values of functions like sqrt() or atan2() are not known up fron then you can fall back to real functions for values that are out of range of your lookup tables.
Avoid to many function calls. Instead of an anonymous function that you pass to patientArray.sort(), that calls GetDistanceToPoint(), that calls degreeToRadius() - you need only one function that can be passed directly as an argument to .sort() and that function doesn't need to return d - it can return just c (in your example).
You don't need to multiply everything by earthRadius if you only use that value for sorting.
Another quick ideas: using typed arrays (for lookup tables), and asm.js and SIMD.js for additional optimization if possible.
Those are the first things that come to mind. I'd love to hear how much faster your code can get. Good luck.
UPDATE 2:
Another idea - instead of (or in addition to) optimizing the GetDistanceToPoint() you can also make sure that it isn't called more than once for every object.
Instead of:
patientArray.sort(function(a, b)
{
return GetDistanceToPoint(a["Lat"], a["Lng"]) - GetDistanceToPoint(b["Lat"], b["Lng"]);
});
You can try doing something like:
patientArray.forEach(function (element) {
element.distance = GetDistanceToPoint(element["Lat"], element["Lng"]);
});
or maybe for loop will be faster:
for (var i = 0; i < patientArray.length; i++) {
var element = patientArray[i];
element.distance = GetDistanceToPoint(element["Lat"], element["Lng"]);
}
to store the value for the entire patientArray array.
And then in the sort function:
patientArray.sort(function(a, b)
{
return a.distance - b.distance;
});
It may hopefully save you a lot of calls to GetDistanceToPoint.

Solving simulataneous equations with Coffeequate

I'm looking for a Computer Algebra System to run in a browser, with a particular interest in finding roots to systems of equations.
I'm currently evaluating Coffeequate.
The simplest non-trivial system I came up with that wasn't on the demo page was a system of two simultaneous linear equations:
var exp1 = CQ('x = 2 * y + 6');
var exp2 = CQ('x - y = 10');
exp2.sub({x: exp1.solve('x')})
.solve('y');
Unfortunately, this hangs at the sub call.
What I would like to obtain is the value for all unknowns (i.e. x and y) that are knowable – there is guaranteed to be a solution in this case.
What am I doing wrong here?
CQ().solve returns an array of solutions (in case there are multiple solutions). However, things that you want to substitute in using CQ().sub have to be integers or CQ() objects themselves. The following code works:
var exp1 = CQ('x = 2 * y + 6');
var exp2 = CQ('x - y = 10');
exp2.sub({x: exp1.solve('x')[0]}).solve('y'); // 4
The fact that it actually hangs instead of erroring when you pass in an array is a bug; I'll patch that.
(Disclaimer: I wrote Coffeequate)

Calculate speed from velocity vector using box2d GetLinearVelocity();

I need to find the speed of an object in a game. The game is made in HTML5 with jquery and jquery.box2d.
For this I can use these methods:
GetLinearVelocity().x;
GetLinearVelocity().y;
I'm then trying to calculate the speed from this piece of code, but get some values that doesn't make sense when I console.log it. This is my code:
var heroVelX = game.currentHero.GetLinearVelocity().x;
var heroVelY = game.currentHero.GetLinearVelocity().y;
var speed = Math.sqrt(heroVelX^2 + heroVelY^2);
console.log(speed);
Some of the values in console.log are numbers, but most of them are NaN (Not-A-Number), which confuses me? Can someone help me solve this?
The goal I want to achieve, is to see when the speed(of object .currenHero) drop below a certain value, so I can excute a new state in the game.
Your problem is that you're using the wrong operator (Bitwise XOR) for doing square - see here.
What you need to do is:
var speed = Math.sqrt(Math.pow(heroVelX, 2) + Math.pow(heroVelY, 2));
The only time the square root function should return NaN is when the value being square rooted is negative. A way to go about testing if this is the issue would be to try squaring the values in a different line of code before square rooting them.
heroVelX = (heroVelX) * (heroVelX)
Another way to potentially shine some light on the problem would be to add log statements printing out the values of the velocities and the velocities squared before square rooting.

Precision decimals, 30 of them, in JavaScript (Node.js)

My Challenge
I am presently working my way through reddit's /r/dailyprogrammer challenges using Node.js and have caught a snag. Being that I'm finishing out day 3 with this single exercise, I've decided to look for help. I refuse to just move on without knowing how.
Challenge #6: Your challenge for today is to create a program that can calculate pi accurately to at least 30 decimal places.
My Snag
I've managed to obtain the precision arithmetic I was seeking via mathjs, but am left stumped on how to obtain 30 decimal places. Does anyone know a library, workaround or config that could help me reach my goal?
/*jslint node: true */
"use strict";
var mathjs = require('mathjs'),
math = mathjs();
var i,
x,
pi;
console.log(Math.PI);
function getPi(i, x, pi) {
if (i === undefined) {
pi = math.eval('3 + (4/(2*3*4))');
i = 2;
x = 4;
getPi(i, x, pi);
} else {
pi = math.eval('pi + (4/('+x+'*'+x+1+'*'+x+2+')) - (4/('+x+2+'*'+x+3+'*'+x+4+'))');
x += 4;
i += 1;
if (x < 20000) {
getPi(i, x, pi);
} else {
console.log(pi);
}
}
}
getPi();
I have made my way through many interations of this, and in this example am using the Nilakatha Series:
This question uses some algorithm to compute digits of pi, apparently to arbitrary precision. Comments on that question indicate possible sources, in particular this paper. You could easily port that approach to JavaScript.
This algorithm has, as an alternating series, an error of about 4/n^3 if the last term is 4/((n-2)*(n-1)*n), that is, using n-3 fraction terms. To get an error smaller than 0.5*10^(-30), you would need (at least) n=2*10^10 terms of this series. With that number, you have to take care of floating point errors, especially of cancellation effects when adding a large number and a small number. The best way to avoid that is to start the summation with the smallest term and then go backwards. Or do the summation forward, but with a precision of 60 decimals, to then round the result to 30 decimals.
It would be better to use the faster converging Machin formula, or one of the Machin-like formulas, if you want to have some idea of what exactly you are computing. If not, then use one of the super fast formulas used for billions of digits, but for 30 digits this is likely overkill.
See wikipedia on the approximations of pi.

simplifying the contents of an input using the javascript math system

This obviuosly works perfectly:<script>alert(5*8-4)</script>
but i need to solve whatever someone puts inside an input box.
Heres what I thought of doing: I would get the value of the input, into a variable. then I would use
document.write("<script>alert("+theinputvalue+")<script>");
or do this:
var string="<script>alert("+theinputvalue+")<script>";document.write(string);
but nothing works.
Is it even possible to do this? if not, tell my what simple other system I could use.
eventually, I will use it to graph lines like this:
var canvas = document.getElementById("canvas"),
ctx = canvas.getContext("2d")
for(var x=-100; x<100; x=x+.2){
y = .1*(x*x)
ctx.fillRect(x+50, -1*y+50, 2, 2);
}
http://jsfiddle.net/KGgq4/
eval('5*8-4')
will result in 36
I'm not aware of any library that is doing that (this doesn't mean that there are no such it simply means I never actually needed that) but what you should end up doing is to build an automata that will parse input string and transform it to a proper graph with proper transformations. This is not very easy topic and if you want to go this route you should start reading on arithmetic expressions parsing algorithms (sorry I do not have any solution in place).
Or you can cheat and define types of equations that will be selected by user. Once user selects type of equation you should be able show user inputs where user will be able to select coefficients. You can read those coefficients into different variables and apply transformations in your draw procedure (For example if user will select type sin(x) you know that general equation has following formula: y = k*sin(a*x + b) + c. So once it is selected you can allow user to enter k, a, b, c and based on that input calculate appropriate locations of points for your graph.)
Well, third solution could involve "eval ", but usually you should avoid eval at any cost (B/c it is straight forward JavaScript injection which may be an OK for this case but may get you in trouble later in your life. ).
You can use math.js, which comes with an advanced expression parser. It supports definition of variables and functions.
// create an instance of math.js
var math = mathjs();
// evaluate an expression
math.eval('5*8-4'); // 36
// user defined function (returns a native JavaScript function)
var f = math.eval('f(x) = 2*x^2 + 6');
// use the function (for graphing or something)
f(2); // 14

Categories