Linearly scaling a number in a certain range to a new range - javascript

I've made a scaling function that takes numbers in an interval [oldMin,oldMax] and scales them linearly to the range [newMin,newMax] . It does not seem to work when using negative values.
function linearScaling(oldMin, oldMax, newMin, newMax, oldValue){
var newValue;
if(oldMin !== oldMax && newMin !== newMax){
newValue = parseFloat((((oldValue - oldMin) * (newMax - newMin)) / (oldMax - oldMin)) + newMin);
newValue = newValue.toFixed(2);
}
else{
newValue = error;
}
return newValue;
}
This function seems to work when scaling a value from 0 -> 32761 to the range range 0 -> 10. However it does not seem to give the correct output when given a new negative range i.e. -10 -> 10
I have done my best to find an answer on this site. However the person who asked the question didn't mention what he ended up doing to fix it. That question says it could have something to do with mixed up data types, but i converted everything to a float did I miss anything?

Now that you showed how you call your function, I can reproduce your problem - namely that quoted numbers that should map to the negative domain don't.
It seems to be due to the fact that Javascript is very loose about the difference between a number and a string - and if it's not sure what to do about two numbers (because one of them appears to be a string), it assumes you want concatenation rather than addition. In other words - by passing the newMin value as '-10' rather than -10 you confused JS.
As a simple example,
document.write('1' + '-2');
produces
1-2
However,
document.write(1*'1' + 1*'-2');
results in
-1
The expression you had included a "possible concatenation" where it added oldMin:
newValue = (((oldValue - oldMin) * (newMax - newMin)) / (oldMax - oldMin)) + newMin;
With newMin set to '-10', you might get newValue to look like 6-10 instead of -4, to give an example. When you then did a parseFloat, Javascript would quietly work its way through the string up to the minus sign, and return 6 instead of evaluating the expression and coming up with -4.
To clear up the confusion, multiply each parameter by 1 to make it "a genuine number":
oldMin = 1*oldMin;
oldMax = 1*oldMax;
newMin = 1*newMin;
newMax = 1*newMax;
oldValue = 1*oldValue;
When you add these lines at the start of your function declaration, everything works smoothly - regardless of how you call the function. Or just call it with the newMin value not in quotes - it is the one causing the trouble in this particular instance.
document.writeln('the new code called with parameter = 100:\n');
document.writeln(linearScaling('0', '32761', '-10', '10', 100)+'<br>');
document.writeln('the old code called with parameter = 100:\n');
document.writeln(linearScalingOld('0.0', '32761.0', '-10.0', '10.0', '100.0')+'<br>');
document.writeln('the old code called with unquoted parameters:\n');
document.writeln(linearScalingOld(0.0, 32761.0, -10.0, 10.0, 100.0)+'<br>');
results in the following:
the new code called with parameter = 100: -9.94
the old code called with parameter = 100: 0.06
the old code called with unquoted parameters: -9.94
I hope this illustrates the cause of the problem, and the solution.

Related

Great common divisor with loops

I think my logic is wrong but I can't understand where I am making a mistake. I am trying to find the great common divisor, and code will determine what to do if a is bigger than b or b is bigger than a.
I tried many loops, if, while but in the end I deleted all to clear my sight. I made flowchart however it is not coming along with my code.
var a = 64;
var b = 12;
var newA;
while(a > b && newA != 0){
newA = a - b;
if(newA === 0){
outputObj.innerHTML = outputObj.innerHTML + "GCD is " + b;
}
}
while(a < b && newA != 0){
newA = b - a;
}
if(newA === 0){
outputObj.innerHTML = outputObj.innerHTML + "GCD is " + a;
}
}
If a is 64 and b is 12 the GCD is 4, if a is 35 and b is 42 the GCD is 7
You have a few different problems here. This looks like homework, so I'll try to point you in the right direction for a couple of the problems rather than e.g. telling you exactly what your code should say.
In your loops, you never update the value of either a or b.
Pretending that that's fixed, your code will either subtract a from b several times or subtract b from a lots of times. Doing that computes the remainder on dividing one number by the other, not the greatest common divisor.
I'm betting that you've been given a description of an algorithm for computing the greatest common divisor. Read through it again, comparing what it does against what your code does.
Here's a powerful method for finding problems in this sort of code: try to run it in your head, pretending that you're the computer. Go through, step by step, doing what the computer will do. With your code above, it might begin like this:
OK, I've got variables called a and b, whose values are 64 and 12. And a variable called newA, whose value hasn't been specified yet.
Now I need to check whether a is bigger than b -- yup, it is -- and then whether newA is zero.
Wait, I haven't given newA a value at this point. (You've found a bug here. Let's pretend it's fixed and move on.)
Now I set newA to be a-b, which is 52.
Now I check whether newA is zero, which it isn't so I don't need to do the stuff inside the if block there.
OK, so we've done one iteration of the while loop. Back to the start of the loop.
Now I need to check whether a is bigger than b -- yup, it is -- and then whether newA is zero.
Wait a minute, I'm checking the exact same thing as last time: nothing's changed. How's this loop going to end? (You've found another bug here.)
And so on.

Formula not calculating correctly in JavaScript

I'm experiencing an issue with a formula in JavaScript.
var animMoveX = $(this).attr('data-start') + (animPercentage / 100) * ($(this).attr('data-finish') - $(this).attr('data-start'));
To my eyes it's a fairly simple piece of math, but the console outputs 120-[variable no relative to animPercentage, eg. 126.49681528662421].
I've double-checked all variables, and they are correct, and if I replace one of the $(this).attr('data-start') variable in one of the positions with a fixed number, then the calculation is run just fine. Can someone shed some light on why this is, and how I could potentially work around it?
From my comment: Precedence means it will calculate a number on the right and add it to the string from data-start (i.e. using string concatenation). That needs to be converted to a number too. #Pointy's suggestion will do that as data converts strings to appropriate data types (when it can).
So basically change all the attr() calls to data() calls and "numbers" (stored in attributes) will become numbers:
var animMoveX = $(this).data('start') + (animPercentage / 100) * ($(this).data('finish') - $(this).data('start'));
As an added bonus, using data instead of attr is shorter code too :)

Is it possible to convert A string that is an equation with a variable into a equation?

I need to convert a string returned from prompt into an equation, however the parseFloat returns as only the first number, and symbols in an equation, and stops at the variable. The variable will always = x. The program is designed to convert an algebraic expression say 15*x(5^4-56)*17/x=15 into an expression, and calculate the value of x. If someone could show me how to do this, it would help dramatically. I am currently using multiple prompts, having the user put in the equation before x, then the equation after x, then it inserts a variable in between the two, and calculates it's value.
Edit:
I have no variables predefined, and it must work in equations where x > 1000, or x != //an integer.
Thanks in advance!
Seems to be a complex problem...
This is a solution for a simple relaxed version of your problem. Hope you can use some components of this.
Constraints:
answer for x should be integers between 0 and 1000
the left hand side of the expression should be proper javascript syntax
var input = prompt("enter the equation"); //eg: x*x+x+1=241
var parts = input.split('=');
//solving equation starts
var x = 0;
var temp = eval(parts[0]);
while (temp != parts[1] && x<1000){
x++;
temp = eval(parts[0]);
}
var ans = (x<1000)?"answer is "+x:"this program cannot solve this";
//solving equation finishes
alert(ans);
You can replace the "solving equation" part with some numerical methods used in computer science to solve equations (more details here) . You will have to parse the left side of equation and map them to proper javascript expressions (as a string to execute with eval()) if you want to allow users to use your syntax.
Javascript can evaluate strings using the eval function, but the variable as to be defined before hand, and the equation has to be formatted in way that javascript can understand:
var x = 15
var string = "15*x*17/x"
eval(string)
Your example: "15*x(5^4-56)*17/x=15" would not run however, because it would evaluate x(5^4-56) as a javascript expression, which is invalid.
Using all the info, and other mehtods I found about this, I have put together a communinty answer. Anyone is invited to change and/or add their methods to this.
In order to do this with the least work possible for the user and coder, you would implement the following code.
var input = prompt("enter the equation"); //eg: x*x+x+1=241
var parts = input.split('=');
//solving equation starts
var x = 0; //Or the lowest possible value of "x"
var temp = eval(parts[0]);
while (temp != parts[1] && x<1000){ // && x < The highest number to evaluate
x++; //Add the increment (determines the maximum amount of digits) eg x+0.1 for tenths max, x+2 for only even integers etc.
temp = eval(parts[0]);
}
var ans = (x<1000)?"answer is "+x:"this program cannot solve this"; //make sure x< is the same as line 7.
//solving equation finishes
alert(ans);
But, this runs very slowly if you allow tenths, or a range larger than 2000.`
A faster way of running this would be to define arrays allowing any variable (instead of just x) and a different eveulation process such as here. (do the right click view html and click on the first js source to see code) but, this is 2k lines. Both are usable, but the second is more efficient, and can solve multivariate equations.

Save integers as floats [duplicate]

This question already has answers here:
Save integer as float
(2 answers)
Closed 8 years ago.
function prec(numb){
var numb_string = numb.toString().split('.')
return numb_string[(numb_string.length - 1)].length
}
function randy(minimum, maximum) {
var most_accurate = Math.max ( prec(minimum), prec(maximum) );
return ( ( Math.random() * ( maximum - minimum ) + minimum ).toFixed( most_accurate ) );
}
// returns random numbers between these points. 1 decimal place of precision:
console.log( randy(2.4,4.4) );
// returns random numbers between these points. 3 decimal places of precision:
console.log( randy(2.443,4.445) );
// returns random numbers between these points. Want 3 decimal places of precision. However, get 0:
console.log( randy(2.000,4.000) );
// Why do I get 0 decimal places? Because floats are rounded into integers automatically:
console.log( 4.0 ); // want 4.0 to be logged. Instead I get '4'
You don't need to read how the functions work. Just the console logs.
Basically, I need to return a random number between two points to a degree of precision. The precision is automatically derived from the most precise float passed to the randy function.
This works fine when the number range is 3.5 3.7 or 34.4322 800.3233 but not 2.0, 3.0 or 4.0000, 5.0000
Then the number is appears to be automatically saved as an integer:
console.log( 2.0 ) //=> 2
I want to extend the Number prototype so that 2.0 is saved as 2.0 so that this function can find the precision:
function prec(numb){
var numb_string = numb.toString().split('.')
return numb_string[(numb_string.length - 1)].length
}
It currently thinks that 3.000000000 has a precision of 0 decimal places because if 3E8 is passed in as the numb parameter, it's read as 3. I want it read as 3.000000000
While I can do this randy(2.toFixed(3),3.toFixed(3)) it gets unreadable and it would be undeniably nicer to do this for smaller precisions: randy(2.000,3.000).
Is this possible?
Fiddle
There is only one number type in JS.
Aside from shortfalls of the type itself (causing headaches in other languages as well), it's a good thing.
If you want to display precision, then use num.toFixed(n); to store the number as a string, rounded to the precision you requested.
You can parse the string later in your code, operate on it, and then call .toFixed(n); on the result, to perpetuate the precision...
But unless you have specific needs, or are lumping several pieces of code together, are you not going to be concerned with rounding inaccuracies, versus just operating on full-precision values, and then rounding/formatting the end results?
Of course there are plenty of other solutions...
...keep track of the mandated precision with an int, representing the value... ...or keep an int representing the floating value as an int, based on preferred precision... 1.235 becomes [1, 235].
...anything is doable.
Subclassing, though, is really not going to be the answer.
you can define a class that helps you solve the problem especially with the toSting function
function NewNumber()
{
this.value = (typeof(arguments[0]) == "number") ? arguments[0] : 0;
this.decimal = (typeof(arguments[1]) == "number") ? arguments[1] : 0;
this.Val = function()
{
return parseFloat(this.value.toFixed(this.decimal));
}
this.toString = function()
{
return (this.value.toFixed(this.decimal)).toString();
}
}
Create a number like this
var Num = NewNumber(4.123545,3);
// first argument is the value
// and second one is decimal
To get the value of your variable, you should use the function Val like this
console.log(Num.Val()); // this one prints 4.123 on your console
Then the toString function
Num.toString() // it returns "4.123"
(new NewNumber(4,4)).toString(); // it returns "4.0000"
in your functions use the toString of the NewNumber class to solve your problem

Neural Network Continuous tanh-Sigmoid Activation Function and Random Weights

I really need help implementing a continuous tanh-sigmoid activation function in a very basic neural network. If you could give a basic example that would be great, but if you could change it in my source code I would be extremely grateful! Also, what range should the random weights be initiated with (i.e. what range)?
The weight range depends on what input data range you have. In some implementations the weights can also be negative.
For possible Sigmoid functions, check here (tanh is not the only possibility):
http://en.wikipedia.org/wiki/Sigmoid_function
Tip: You can typically compute the NN with matrix multiplications.
http://www.dtreg.com/mlfn.htm
http://en.wikipedia.org/wiki/Neural_network
P.S.: probably not a good idea to do this in JavaScript.
you can either implement it via exp(x) , See: http://www.javascripter.net/faq/mathfunc.htm
sinh(x) exp(x) - exp(-x) exp(2x) - 1
tanh(x) = ------- = ------------------ = -------------
cosh(x) exp(x) + exp(-x) exp(2x) + 1
that gives you:
function tanh(x) {
e = Math.exp(2*x);
return (e - 1) / (e + 1) ;
};
another solution is to store a table with the tanh function values in an array, and define a JavaScript function which interpolates the tanh values for x based on the tanh values stored in the array
typically people don't want [-inf...+inf] as the range of the input values, and don't want [-1...+1] as the range of output values -- therefore you might need a different sigmoid function!
you need to take the expected range of input values, and the expected range of output values, and use those to shift the actual sigmoid function, the weight-ranges and the value of the threshhold.
a threshhold of 0.7 or larger is typically used. You need to experiment with that.
this.output = 2 / (1 + Math.exp(-2 * input)) - 1;

Categories

Resources