Polyline Length - javascript

I get line length by this functions.
google.maps.LatLng.prototype.kmTo = function(a){
var e = Math, ra = e.PI/180;
var b = this.lat() * ra, c = a.lat() * ra, d = b - c;
var g = this.lng() * ra - a.lng() * ra;
var f = 2 * e.asin(e.sqrt(e.pow(e.sin(d/2), 2) + e.cos(b) * e.cos
(c) * e.pow(e.sin(g/2), 2)));
return f * 6378.137;
}
google.maps.Polyline.prototype.inKm = function(n){
var a = this.getPath(n), len = a.getLength(), dist = 0;
for (var i=0; i < len-1; i++) {
dist += a.getAt(i).kmTo(a.getAt(i+1));
}
return dist;
}
And use :
alert('Line Length: '+ poly1.inKm() +'');
Everything working. But i have a small problem.
Its shows me: >> Line Length: 8.854502612255438km <<
Digits is to long i want it show me only 8.8 how can i do it?
Sorry for my english!

Try something like:
Math.floor(x * 10) / 10
Where x is the number you are trying to show (8.854502612255438).
Instead of floor (which will turn 88.5 to 88) you may want to try round (which will turn 88.5 to 89).
Edit - ah no, that won't work will it because your number is a string with 'km' at the end (did not spot that)...
so... try using parseFloat like this:
Math.floor(parseFloat(x, 10) * 10) / 10
You would have to add 'km' to the end of the string your self, so the full thing becomes:
alert('Line Length: '+ (Math.floor(parseFloat(poly1.inKm(), 10) * 10) / 10) +'km');

Related

SyntaxError: identifier starts immediately after numeric literal while trying to create a BigInt in javascript

I am trying to solve Pi till n number of digits in JavaScript with this formula:
#!/usr/bin/env js60
function calculatePi(n) {
var q = t = k = 1
var m = x = 3
var n = n + 1
var r = 0
str = ''
while (str.length < n) {
if (4 * q + r - t < m * t) {
str += m
var rr = r
r = 10 * (r - m * t)
m = Math.floor((10 * (3 * q + rr)) / t - 10 * m)
q = 10 * q
}
else {
m = Math.floor(((q * (7 * k + 2)) + (r * x)) / (t * x))
r = ((2 * q) + r) * x
t = t * x
q = q * k
k = k + 1
x = x + 2
}
}
return str.slice(0, 1) + '.' + str.slice(1)
}
print(calculatePi(19))
Here's how it works in a language with arbitrary length integer support.
But in JavaScript the code generate correct values till the 18 decimal places, and after that the number gets really big to work with. Worse, if the function is given a large number like 10000, it will run in a infinite loop.
When I am trying to write a big number with an n appended to it (as suggested here):
var a = 1000000000000000000000000000n
I get:
typein:1:8 SyntaxError: identifier starts immediately after numeric literal:
typein:1:8 var a = 1000000000000000000000000000n
typein:1:8 ........^
How can I represent an arbitrary length integer in JavaScript?
Thanks to the comments, changing the JS engine from SpiderMonkey to Node solved the issue. The final code looked like:
#!/usr/bin/env node
function calculatePi(n) {
var one = 1n, two = 2n, three = 3n, seven = 7n, ten = 10n
var q = t = k = one
var m = x = three
var n = BigInt(n) + one
var r = 0n
str = ''
while (str.length < n) {
if (4n * q + r - t < m * t) {
str += m
var rr = r
r = ten * (r - m * t)
m = (ten * (three * q + rr)) / t - ten * m
q *= ten
}
else {
t *= x
m = (q * (seven * k + two) + (r * x)) / t
r = ((two * q) + r) * x
q *= k
k += one
x += two
}
}
return str.slice(0, 1) + '.' + str.slice(1)
}
console.log(calculatePi(5000))
Now it can solve any digits using some system's memory (around 40 MiB for 5,000 digits).
The code removed Math.floor() function because BigInt calculation are Integers. A floating point number with arbitrary precision is not going to be calculated here.

I'm trying to port a 1D perlin noise tutorial on C++

I'm trying to port a 1D perlin noise tutorial on C++ using SFMl lib : (tutorial link in javascript) https://codepen.io/Tobsta/post/procedural-generation-part-1-1d-perlin-noise
However this doesn't work, i don't get any error but this is what i get : https://i.imgur.com/2tAPhsH.png .
basically a straight line
And this is what i should get : https://i.imgur.com/GPnfsuK.png
Here's the ported code from the above link :
TerrainBorder constructor:
TerrainBorder::TerrainBorder(sf::RenderWindow &window) {
M = 4294967296;
A = 1664525;
C = 1;
std::random_device rd;
std::mt19937 rng(rd());
std::uniform_int_distribution<int> dist(0, M);
Z = floor(dist(rng) * M);
x = 0;
y = window.getSize().y / 2.0f;
amp = 100;
wl = 100;
fq = 1.0f / wl;
a = rand();
b = rand();
ar = sf::VertexArray(sf::Points);
}
Functions:
double TerrainBorder::rand()
{
Z = (A * Z + C) % M;
return Z / M - 0.5;
}
double TerrainBorder::interpolate(double pa, double pb , double px) {
double ft = px * PI,
f = (1 - cos(ft)) * 0.5;
return pa * (1 - f) + pb * f;
}
void TerrainBorder::drawPoints(sf::RenderWindow &window) {
while (x < window.getSize().x) {
if (static_cast<int> (x) % wl == 0) {
a = b;
b = rand();
y = window.getSize().y / 2 + a * amp;
} else {
y = window.getSize().y / 2 + interpolate(a, b, static_cast<int> (x)
% wl / wl) * amp;
}
ar.append(sf::Vertex(sf::Vector2f(x, y)));
x += 1;
}
}
Then i'm drawing the sf::VectorArray (which contains all the sf::Vertex in the game loop
i solved my problem ty for the answer anyway :)
I had to deal with types problems :p
I figured out that :
double c = x % 100 / 100;
std::cout << c << std::endl; // 0
!=
double c = x % 100;
std::cout << c / 100 << std::endl; // Some numbers depending on x
If it can help anyone in the future :)
C++ requires a careful choice for the types of the numeric variables, to avoid overflows and unexpected conversions.
The snippet shown in OP's question doesn't specify the types of M, A and Z, but uses a std::uniform_int_distribution of int, while M is initialized with a value that's out of the range of an int in most implementations.
It's also worth to be noted that the Standard Library already provides a std::linear_congruential_engine:
#include <iostream>
#include <random>
int main()
{
std::random_device rd;
std::mt19937 rng(rd());
// Calculate the first value
constexpr std::size_t M = 4294967296;
std::uniform_int_distribution<std::size_t> ui_dist(0, M);
std::size_t Z = ui_dist(rng);
// Initialize the engine
static std::linear_congruential_engine<std::size_t, 1664525, 1, M> lcg_dist(Z);
// Generate the values
for (int i = 0; i < 10; ++i)
{
Z = lcg_dist();
std::cout << Z / double(M) << '\n'; // <- To avoid an integer division
}
}

Weird and unexpected results from a simple series

With a simple JS code I calculate the sum of the following series:
b is a constant, could be any value.
The JS code tries to find for which minimum value r (given it 1000 attempts in this example), this inequality is valid:
If r goes below 1.50000, results get silly.
var pre = 0.0;
var r = 1.50010;
var b = 0.01;
for (var p = 0; p < 1000; p++) {
var sum = 0;
for (var i = 0; i <= 33; i++) {
sum += Math.pow(r, i);
}
sum *= b;
if ((2 * b * Math.pow(r, 34)) > sum) {
pre = r;
r -= 0.00001;
r = parseFloat(r.toFixed(5));
} else {
console.log(pre);
console.log(((2 * b * Math.pow(r + 0.00001, 34)) - sum).toFixed(8));
break;
}
}
The code breaks at pre == 1.5, and if I were to force r = 1.49999, console.log(pre) returns 0. Why?
The code stops when r = 1.5 because that's the minimum value for which your inequality is valid (within the accuracy you're using, anyway). If you start r off at less than that, it's going to break on the first time through the loop since that if statement is never true, so you never set pre to be r.
Here's a graph showing what happens with the two sides of the inequality near r = 1.5:
Code for the above graph:
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(1.4, 1.6, 100)
plt.plot(x , 2 * x ** 34, label = '$2r^{34}$')
plt.plot(x , sum([x ** i for i in xrange(34)]), label = '$\sum_{i = 0}^{33}\/ r^i$')
plt.yscale('log')
plt.legend()
plt.show()
Also, if b is positive, you don't need to do anything with b in your code, since you're multiplying both sides of the inequality by b. And if b is negative, then you need to reverse the inequality.
Oh, and another thing: for algorithms of this type, you may want to consider something more like the bisection method, which halves the search space each time through the iteration. You could use 1 and 2 as the endpoints, since 1 is definitely too low and 2 is definitely too high. You'd stop when the difference between the sides of the inequality fell below some threshold.
I am assuming that when the loop breaks, you want to display the difference between the left and right of the inequality. The problem is because "sum" is a running sum that is from the previous loop, the calculation is not correct.
Now when you force r = 1.49999, the if clause is never executed so "pre" stays at zero as initiated on the first line.
Your full solution should be like this:
var pre = 0.0;
var r = 1.50010;
var b = 0.01;
for (var p = 0; p < 1000; p++) {
var sum = 0;
for (var i = 0; i <= 33; i++) {
sum += Math.pow(r, i);
}
sum *= b;
var diff = (2 * b * Math.pow(r, 34) - sum).toFixed(8);
console.log('diff: ' + diff);
if ((2 * b * Math.pow(r, 34)) > sum) {
pre = r;
r -= 0.00001;
r = parseFloat(r.toFixed(5));
} else {
console.log('--breaking--');
console.log(pre);
//console.log(((2 * b * Math.pow(r + 0.00001, 34)) - sum).toFixed(8));
break;
}
}
and the output is:
diff: 3.91098781
diff: 3.52116542
diff: 3.13150396
diff: 2.74200338
diff: 2.35266364
diff: 1.96348468
diff: 1.57446646
diff: 1.18560893
diff: 0.79691205
diff: 0.40837575
diff: 0.02000000
diff: -0.36821526
--breaking--
1.5

How to make a function that computes the factorial for numbers with decimals?

How can I make a function that calculates the factorial (or the gamma function) of decimal numbers in JavaScript? For example, how could I calculate 2.33!?
I might have found an existing solution...
It's an implementation of Lanczos method, I found it at the swedish wikipedia (http://sv.wikipedia.org/wiki/Gammafunktionen). It was written in python and says to be correct up to 15 decimals. I ported it to js, cross checked some random values against (http://www.efunda.com/math/gamma/findgamma.cfm).
http://jsfiddle.net/Fzy9C/
var g = 7;
var C = [0.99999999999980993, 676.5203681218851, -1259.1392167224028,771.32342877765313, -176.61502916214059, 12.507343278686905, -0.13857109526572012, 9.9843695780195716e-6, 1.5056327351493116e-7];
function gamma(z) {
if (z < 0.5) return Math.PI / (Math.sin(Math.PI * z) * gamma(1 - z));
else {
z -= 1;
var x = C[0];
for (var i = 1; i < g + 2; i++)
x += C[i] / (z + i);
var t = z + g + 0.5;
return Math.sqrt(2 * Math.PI) * Math.pow(t, (z + 0.5)) * Math.exp(-t) * x;
}
}
(and ofcourse it does not support imaginary numbers, since js does not)
As an alternative to the other answers here, here's a much simpler approximation for the gamma function, proposed in 2007 by Gergő Nemes. (See the wikipedia page on Stirling's approximation).
This can be implemented directly in JavaScript in a single line:
function gamma(z) {
return Math.sqrt(2 * Math.PI / z) * Math.pow((1 / Math.E) * (z + 1 / (12 * z - 1 / (10 * z))), z);
}
You can see this in action on jsFiddle.
This is accurate to 8 digits for z > 8, but it is still accurate to a handful of digits for smaller z. It is not quite as accurate as Lanczos approximation, but it is simpler and also slightly faster.
Note that the gamma function and the factorial function are slightly different. The factorial function can be defined in terms of the gamma function thus:
function factorial(n) {
return gamma(n + 1);
}
This is not a trivial problem. There is not a simple closed-form formula for the gamma function. That said, there are some numerical approximations that should suit your needs.
The following answer will be using a technique called Lanczos approximation. The formula is as follows:
where g is an arbitrarily chosen constant that controls how accurate the approximation will be. For larger g, the approximation will be more accurate. Ag(z) is defined thus:
The hardest part is finding Ag(z), since pn is also defined with a complicated formula dependent on g.
I can't take too much credit for the following code, since I am just writing a port of the Python program on the wikipedia page.
function gamma(n) { // accurate to about 15 decimal places
//some magic constants
var g = 7, // g represents the precision desired, p is the values of p[i] to plug into Lanczos' formula
p = [0.99999999999980993, 676.5203681218851, -1259.1392167224028, 771.32342877765313, -176.61502916214059, 12.507343278686905, -0.13857109526572012, 9.9843695780195716e-6, 1.5056327351493116e-7];
if(n < 0.5) {
return Math.PI / Math.sin(n * Math.PI) / gamma(1 - n);
}
else {
n--;
var x = p[0];
for(var i = 1; i < g + 2; i++) {
x += p[i] / (n + i);
}
var t = n + g + 0.5;
return Math.sqrt(2 * Math.PI) * Math.pow(t, (n + 0.5)) * Math.exp(-t) * x;
}
}
and of course, by definition of the gamma function:
function factorial(n) {
return gamma(n + 1);
}
You can see this in action on jsFiddle.
Just to complete #apelsinapa answer to correct the calculation for an integer (we didn't get an integer solution when inputing an integer number).
#apelsinapa's great solution:
var g = 7;
var C = [0.99999999999980993, 676.5203681218851, -1259.1392167224028,771.32342877765313, -176.61502916214059, 12.507343278686905, -0.13857109526572012, 9.9843695780195716e-6, 1.5056327351493116e-7];
function gamma(z) {
if (z < 0.5) return Math.PI / (Math.sin(Math.PI * z) * gamma(1 - z));
else {
z -= 1;
var x = C[0];
for (var i = 1; i < g + 2; i++)
x += C[i] / (z + i);
var t = z + g + 0.5;
return Math.sqrt(2 * Math.PI) * Math.pow(t, (z + 0.5)) * Math.exp(-t) * x;
}
}
And to get a correct answer for integer:
function factorialOfNumber(number) {
if (number % 1 != 0 || number<0){
return gamma(number + 1);
}
else {
if(number == 0) {
return 1;
}
for(var i = number; --i; ) {
number *= i;
}
return number;
}
}
Here's a version I wrote a few years ago ... a bit messy but tested :)
var
M_GAMMA = [76.18009172947146, -86.50532032941677, 24.01409824083091, -1.231739572450155, 0.1208650973866179e-2, -0.5395239384953e-5],
M_GAMMAS = 6;
function gammaFn(x) // Modified to JavaScript from "Numerical Recipies in C" by P. Mainwaring
{
var i = 0, n = ++x, tmp = x + 5.5, ser = 1.000000000190015;
for (tmp -= (x + 0.5) * Math.log(tmp); i < M_GAMMAS; ++i) ser += M_GAMMA [i] / ++n;
return Math.log(2.5066282746310005 * ser / x) - tmp;
}
function fact(x) { return x > 1 ? Math.exp(gammaFn(x)) : 1 }
function combin(n, k) { return (Math.exp(gammaFn(n) - gammaFn(n - k) - gammaFn(k)) + 0.5) | 0 } // Ms Excel COMBIN() n! / k!(n - k)!
n = 49; k = 6; alert(fact(n) + ' ' + fact(k) + ' ' + combin(n, k)); // Lottery odds! (13,983,816)
The gamma and gammaLn functions are then:
function gammaLn(x) { return gammaFn(--x) }
function gamma(x) { return Math.exp(gammaLn(x)) }
:-)
If you're just looking for the function to compute factorials of real numbers then you only need this bit of code from Lanczos approximation:
function = factorial(z) {
var g = 7;
var C = [0.99999999999980993, 676.5203681218851, -1259.1392167224028, 771.32342877765313, -176.61502916214059, 12.507343278686905, -0.13857109526572012, 9.9843695780195716e-6, 1.5056327351493116e-7];
var x = C[0];
for (var i = 1; i < g + 2; i++)
x += C[i] / (z + i);
var t = z + g + 0.5;
return Math.sqrt(2 * Math.PI) * Math.pow(t, (z + 0.5)) * Math.exp(-t) * x;
}
Works great for negative numbers in addition to decimals.

Getting random number divisible by 16

In math how do I obtain the closest number of a number that is divisible by 16?
For example I get the random number 100 and I want to turn that number (using a math function) into the closest number to 100 that is divisible by 16 (In this case its 96)
I'm trying to do this in JavaScript but if I knew the math formula for it I would easily do it in any language.
Thank you,
Regards
Generate a random integer. Multiply it by 16.
Divide by 16, round, and multiply by 16:
n = Math.round(n / 16) * 16;
function GetRandomNumberBetween(lo, hi) {
return Math.floor(lo + Math.random() * (hi - lo));
}
Number.prototype.FindClosestNumberThatIsDivisibleBy = function(n) {
return Math.round(this / n) * n; //simplify as per Guffa
/* originally:
var c = Math.ceil(n);
var f = Math.floor(n);
var m = num % n;
var r = f * n;
if (m > (n / 2))
r = c * n;
return r;
*/
};
var r = GetRandomNumberBetween(10, 100);
var c = r.FindClosestNumberThatIsDivisibleBy(16);
function closest(n) {
var r = 0, ans = 0;
r = n % 16
if r < 8 {
ans = n - r
} else {
ans = n + (16 - r)
}
return ans;
}
Here's how I understand your question. You're given a number A, and you have to find a number B that is the closest possible multiple of 16 to A.
Take the number given, "A" and divide it by 16
Round the answer from previous step to the nearest whole number
multiply the answer from previous step by 16
there's the pseudocode, hope it's what you're looking for ;-)
A general JS solution
var divisor = 16;
var lower = 0;
var upper = 100;
var randDivisible = (Math.floor(Math.random()*(upper-lower))+lower)*divisor;
alert(randDivisible);

Categories