Node-red converting bytes to decimal in function node - javascript

Im trying to figure out the scaling of the value i get from a modbus read node, and ended up doing it the hard way. So i need to convert the 4 bytes from the buffer, to decimal value in a function node.
This way i can easily tweak the scaling and modbus parameters manually.
I thought the easiest way would be:
Bytes -> Bits -> (apply different parameters) -> Decimal value -> apply optional scaling
And thats what i tried making, but it does not work and i dont se why. Either it does nothing(outputs NaN), or node-red just stops running. And i have to disable the flow from the node-red files. Then restart the raspberry pi, then manually start node-red again.
var In = msg.buffer;
var i;
var j;
var Bit;
var Bits = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];
var BitVal8 = [128,64,32,16,8,4,2,1]
var BitVal32 = [1,2,4,8,16,32,64,128]
var Negative;
var Out;
//Sjekker om MSB er 1
if (In[0] >= 128)
{
Negative= true;
In[0] -= 128;
}
//Regner ut verdien av hvert bit i et 32 bit word
for (i= 8; i<32;i++)
{
j = i-1;
BitVal32[i]= (BitVal32[j]*2);
}
//Går gjennom alle 4 bytes (0-3)
for (i= 0; i<4; i++)
{
//Går gjennom alle bits (0-7) og legger de inn rett i 32 bit var
for (j=0; j<8; j++)
{
Bit= (j+1)*(i+1)-1;
if ((In[i]/BitVal8[j])>1)
{
In[i]-= BitVal8[j];
Bits[Bit]=1;
}
}
}
//Konverterer 32 bit var til decimal var
for (i = 0; i < 32; i++)
{
if (Bits[i]==1)
{
Out+=BitVal32[i];
}
}
//Hvis MSB var 1, negates tallet
if (Negative)
{
Out= Out*-1;
}
msg.payload = Out;
node.status({fill:"blue",shape:"ring",text:msg.topic + ": " + msg.payload});
return msg;
I used these nodes for a while. But i cant get them to work with certain variables from the modbus unit. Becuse the modbus parameter is different on them.
Read through this page, but its the opposite of what i want to do and i dont understand it well enough to apply it to my situation.

1: A i++ in the j-for loop caused node red to crash sometimes.
2: The formula to calculate which bit it should write to in the 32 bit var was wrong. was (byte+1)*(bit+1)-1, which works at some times not all. New formula is ((Byte+1)*8-8+bit
3: At the verry last for loop, i add the value of each bit to the output signal. But the BitValue variable went from small to big, not big to small (was LE, should be BE)
New and working code:
var In = msg.buffer;
var i;
var j;
var Bit;
var Bits = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];
var BitVal8 = [128,64,32,16,8,4,2,1]
var BitVal32 = [2147483648]
var Negative;
var Out= 0;
//Sjekker om MSB er 1
if (In[0] >= 128)
{
Negative= true;
In[0] -= 128;
}
//Regner ut verdien av hvert bit i et 32 bit word
for (i= 1; i<32;i++)
{
j = i-1;
BitVal32[i]= (BitVal32[j]/2);
}
//Går gjennom alle 4 bytes (0-3)
for (i= 0; i<4; i++)
{
//Går gjennom alle bits (0-7) og legger de inn rett i 32 bit var
for (j=0; j<8; j++)
{
Bit= (((i+1)*8)-8+j);
if ((In[i]/BitVal8[j])>=1)
{
In[i]-= BitVal8[j];
Bits[Bit]=1;
}
}
}
//Konverterer 32 bit var til decimal var
for (i = 0; i < 32; i++)
{
if (Bits[i]==1)
{
Out+=BitVal32[i];
}
}
//Hvis MSB var 1, negates tallet
if (Negative)
{
Out= Out*-1;
}
msg.payload = Out;
node.status({fill:"blue",shape:"ring",text:msg.topic + ": " + msg.payload});
return msg;

Related

What is the simplest code with a for loop that you would use to represent a Log(n) BigO notation? [duplicate]

Like the Big O notation "O(1)" can describe following code:
O(1):
for (int i = 0; i < 10; i++) {
// do stuff
a[i] = INT;
}
O(n):
for (int i = 0; i < n; i++) {
// do stuff
a[i] = INT;
}
O(n^2):
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
// do stuff
a[i][j] = INT;
}
}
What code can O(log(n)) describe?
Another question:
What solutions are there for "Big O problems" (what to do, when getting a lot of data as an input)?
Classic example:
while (x > 0) {
x /= 2;
}
This will be:
Iteration | x
----------+-------
0 | x
1 | x/2
2 | x/4
... | ...
... | ...
k | x/2^k
2k = x → Applying log to both sides → k = log(x)
Simplest code with a for loop that you would use to represent:
O(1):
function O_1(i) {
// console.log(i);
return 1
}
O(n):
function O_N(n) {
count = 0;
for (i = 0; i < n; i++) {
// console.log(i);
count++;
}
return count
}
O(n²):
function O_N2(n) {
count = 0;
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
// console.log(i, j);
count++;
}
}
return count
}
O(Log2(n)):
function O_LOG_2(n) {
count = 0;
for (var i = 1; i < n; i = i * 2) {
count++;
}
return count
}
O(Sqrt(n)):
function O_SQRT(n) {
count = 0;
for (var i = 1; i * i < n; i++) {
// console.log(i);
count++;
}
return count
}
From definition, log(n) (I mean here log with base 2, but the base really doesn't matter), is the number of times, that you have to multiply 2 by itself to get n. So, O(log(n)) code example is:
i = 1
while(i < n)
i = i * 2
// maybe doing addition O(1) code
In real code examples, you can meet O(log(n)) in binary search, balanced binary search trees, many resursive algoritmhs, priority queues.
For O(logn), please have a look at any code that involves divide and conquer strategy
Example: Merge sort & quick sort(expected running time is O(nlogn) in these cases)
Binary Search is an example O(log(n)). http://en.wikipedia.org/wiki/Binary_search_algorithm.
It might be worth emphasizing that the lower complexity algorithms you described are subsets of the the higher complexity ones. In other words,
for (int i = 0; i < 10; i++) {
// do stuff
a[i] = INT;
}
is in O(1), but also in O(n), O(n²), and, if you wanted to be clever, O(log(n)).Why? Because all constant time algorithms are bounded by some linear, quadratic, etc. functions.
What solutions are there for "Big O problems" (what to do, when getting a lot of data as an input)?
This question doesn't make a lot of sense to me. "A lot of data" is a quite arbitrary. Still, keep in mind that Big O isn't the only measure of time complexity; apart from measuring worst case time complexity, we can also examine best-case and average case, though these can be a bit trickier to calculate.
In the case of binary search, you are trying to find the maximum number of iterations, and therefore the maximum number of times the search space can be split in half. This is accomplished by dividing the size of the search space, n, by 2 repeatedly until you get to 1.
Let's give the number of times you need to divide n by 2 the label x. Since dividing by 2, x times is equivalent to dividing by 2^x, you end up having to solve for this equation:
n/2^x = 1, which becomes n = 2^x,
So using logarithm, x = log(n), so BIG - O of binary search is O(log(n))
To reiterate: x is the number of times you can split a space of size n in half before it is narrowed down to size 1.
http://www.quora.com/How-would-you-explain-O-log-n-in-algorithms-to-1st-year-undergrad-student

Converting a base 10 number to other bases 2 without built in Javascript functions

I am new to coding and javascript and was asked, for an assignment, to convert base 10 numbers to a binary base without using specific Javascript built in methods (like alert(a.toString(16))), and I am only allowed to use loops,arrays and functions. This is what i have so far:
var number = prompt("Enter an unsigned base 10 number");
if (number>=0) {
var base = prompt("Enter b for binary, o for octal, or h for hexadecimal");
if (base=="h"||base=="H") {
;
}
So as you can see, I don't have much to go on. I was curious as to what equation or formula I would use to convert the base 10 number, as well as how i'm supposed to show A=10, B=11, C=12 and so forth for a hexadecimal base. Any help would be greatly appreciated!
edit: This is a rather complicated way to do it,
as Alnitak showed me (see discussion below).
It is more a scibble, or the long way by foot.
Short explanation:
If we want to get the binary of the decimal number 10,
we have to try 2^n so that 2^n is still smaller than 10.
For example 2^3 = 8 (that is OK). But 2^4 = 16 (thats too big).
So we have 2^3 and store a 1 for that in an array at index 3.
Now we have to get the rest of 10-2^3, which is 2, and have to
make the same calculation again until we get a difference of zero.
At last we have to reverse the array because its the other way arround.
var a = prompt("Enter an unsigned base 10 number");
var arr = [];
var i = 0;
function decToBin(x) {
y = Math.pow(2, i);
if (y < x) {
arr[i] = 0;
i++;
decToBin(x);
} else if (y > x) {
i--;
newX = (x - Math.pow(2, i));
arr[i] = 1;
i = 0;
decToBin(newX)
} else if (y == x) {
arr[i] = 1;
result = arr.reverse().join();
}
return result;
}
var b = decToBin(a); // var b holds the result
document.write(b);

Seeking a statistical javascript function to return p-value from a z-score

I need to convert z-scores to percentile. I found reference to a function in the jStat library that I could use (jstat.ztest), but the jStat documentation seems to be ahead of the available library because there is no such function in the currently available version of the library.
I think there is a more recent version of the library on GitHub, which may include the ztest function, but I am a linux novice and could not figure out how to build the library from the instructions. I spent most of a day learning about git bash and cygwin trying to build the library; I finally decided I'd be better off asking here.
So, could anyone point me toward a javascript function that would do what I need?
Alternatively, could anyone point me toward a built version of the jStat library with ztest function included?
I found this in a forum online and it works like a charm.
function GetZPercent(z)
{
//z == number of standard deviations from the mean
//if z is greater than 6.5 standard deviations from the mean
//the number of significant digits will be outside of a reasonable
//range
if ( z < -6.5)
return 0.0;
if( z > 6.5)
return 1.0;
var factK = 1;
var sum = 0;
var term = 1;
var k = 0;
var loopStop = Math.exp(-23);
while(Math.abs(term) > loopStop)
{
term = .3989422804 * Math.pow(-1,k) * Math.pow(z,k) / (2 * k + 1) / Math.pow(2,k) * Math.pow(z,k+1) / factK;
sum += term;
k++;
factK *= k;
}
sum += 0.5;
return sum;
}
And I don't need to include a large library just for the one function.
Just editing the code from Paul's answer for a two-sided t-test
function GetZPercent(z)
{
//z == number of standard deviations from the mean
//if z is greater than 6.5 standard deviations from the mean
//the number of significant digits will be outside of a reasonable
//range
if ( z < -6.5)
return 0.0;
if( z > 6.5)
return 1.0;
if (z > 0) { z = -z;}
var factK = 1;
var sum = 0;
var term = 1;
var k = 0;
var loopStop = Math.exp(-23);
while(Math.abs(term) > loopStop)
{
term = .3989422804 * Math.pow(-1,k) * Math.pow(z,k) / (2 * k + 1) / Math.pow(2,k) * Math.pow(z,k+1) / factK;
sum += term;
k++;
factK *= k;
}
sum += 0.5;
return (2*sum);
}
This seems like such a simple ask but I had a hard time tracking down a library that does this instead of copying some random code snippet. Best I can tell this will calculate z-score from a percentage using the simple-statistics library.
I took their documentation about cumulativestdnormalprobability and backed into the following algorithm. Feels like there should be an easier way but who knows.
https://simplestatistics.org/docs/#cumulativestdnormalprobability
const z_score = inverseErrorFunction((percentile_value - 0.5) / 0.5) * Math.sqrt(2);
As already correctly stated by Shane, the equation is an implementation of the Taylor Expansion of the normal cdf. The sum value iterates above and below the "real" value with increasing precision. If the value is close to 1 or 0 there is a very low, but existing, probability that sum will be >1 or <0, because of the (relatively) early break by loopstop.
The deviation is further strengthened by rounding 1/Math.sqrt(2*Math.Pi) to 0.3989422804 and the precision issues of javascript float numbers. Additionally, the provided solution will not work for z-scores >7 or <-7
I updated the code to be more accurate using the decimal.js npm library and to directly return the p-value:
function GetpValueFromZ(_z, type = "twosided")
{
if(_z < -14)
{
_z = -14
}
else if(_z > 14)
{
_z = 14
}
Decimal.set({precision: 100});
let z = new Decimal(_z);
var sum = new Decimal(0);
var term = new Decimal(1);
var k = new Decimal(0);
var loopstop = new Decimal("10E-50");
var minusone = new Decimal(-1);
var two = new Decimal(2);
let pi = new Decimal("3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117067982148086513282306647")
while(term.abs().greaterThan(loopstop))
{
term = new Decimal(1)
for (let i = 1; i <= k; i++) {
term = term.times(z).times(z.dividedBy(two.times(i)))
}
term = term.times(minusone.toPower(k)).dividedBy(k.times(2).plus(1))
sum = sum.plus(term);
k = k.plus(1);
}
sum = sum.times(z).dividedBy(two.times(pi).sqrt()).plus(0.5);
if(sum.lessThan(0))
sum = sum.abs();
else if(sum.greaterThan(1))
sum = two.minus(sum);
switch (type) {
case "left":
return parseFloat(sum.toExponential(40));
case "right":
return parseFloat((new Decimal(1).minus(sum)).toExponential(40));
case "twosided":
return sum.lessThan(0.5)? parseFloat(sum.times(two).toExponential(40)) : parseFloat((new Decimal(1).minus(sum).times(two)).toExponential(40))
}
}
By increasing the Decimal.js precision value and decreasing the loopstop value you can get accurate p-values for very small (or very high) z-scores for the cost of calculation time.

Generate all combinations for pair of bits set to 1?

I'm trying to generate all possible combinations for pair of 1's within given bit width.
Let's say the bit width is 6, i.e. number 32. This is what I would like to generate:
000000
000011
000110
001100
001111
011000
011011
011110
110000
110011
110110
111100
111111
If I have variables:
var a = 1,
b = 2;
num = a | b;
and create a loop that I'll loop over width - 1 times, and where I shift both a << 1 and b << 1, I'll get all combinations for one pair. After that, I'm pretty much stuck.
Could someone , please, provide some help.
Update: working example
Based on Barmar's mathematical approach, this is what I managed to implement
var arr = [],
arrBits = [];
function getCombs(pairs, startIdx) {
var i, j, val = 0, tmpVal, idx;
if (startIdx + 2 < pairs) {
startIdx = arr.length - 1;
pairs -= 1;
}
if (pairs < 2) {
return;
}
for (i = 0; i < pairs-1; i++) {
idx = startIdx - (i * 2);
val += arr[idx];
}
for (j = 0; j < idx - 1; j++) {
arrBits.push((val + arr[j]).toString(2));
}
getCombs(pairs, startIdx-1);
}
(function initArr(bits) {
var i, val, pairs, startIdx;
for (i = 1; i < bits; i++) {
val = i == 1 ? 3 : val * 2;
arr.push(val);
arrBits.push(val.toString(2));
}
pairs = Math.floor(bits / 2);
startIdx = arr.length - 1;
getCombs(pairs, startIdx);
console.log(arrBits);
}(9));
Working example on JSFiddle
http://jsfiddle.net/zywc5/
The numbers with exactly one pair of 1's are the sequence 3, 6, 12, 24, 48, ...; they start with 3 and just double each time.
The numbers with two pairs of 1's are 12+3, 24+3, 24+6, 48+3, 48+6, 48+12, ...; these are the above sequence starting at 12 + the original sequence up to n/4.
The numbers with three pairs of 1's are 48+12+3, 96+12+3, 96+24+3, 96+24+6, ...
The relationship between each of these suggests a recursive algorithm making use of the original doubling sequence. I don't have time right now to write it, but I think this should get you going.
if the bit width isn't that big then you'll be way better off creating bit representations for all numbers from 0 to 31 in a loop and simply ignore the ones that have an odd number of "ones" in the bit representation.
Maybe start counting normally in binary and replace all 1's with 11's like this:
n = 5
n = n.toString(2) //= "101"
n = n.replace(/1/g, "11") //= "11011"
n = parseInt(n, 2) //= 27
So you'll get:
0 -> 0
1 -> 11
10 -> 110
11 -> 1111
100 -> 1100
101 -> 11011
110 -> 11110
111 -> 111111
And so on. You'll have to count up to 31 or so on the left side, and reject ones longer than 6 bits on the right side.
See http://jsfiddle.net/SBH6R/
var len=6,
arr=[''];
for(var i=0;i<len;i++){
for(var j=0;j<arr.length;j++){
var k=j;
if(getNum1(arr[j])%2===1){
arr[j]+=1;
}else{
if(i<len-1){
arr.splice(j+1,0,arr[j]+1);
j++;
}
arr[k]+=0;
}
}
}
function getNum1(str){
var n=0;
for(var i=str.length-1;i>=0;i--){
if(str.substr(i,1)==='1'){n++;}
else{break;}
}
return n;
}
document.write(arr.join('<br />'));
Or maybe you will prefer http://jsfiddle.net/SBH6R/1/. It's simpler, but then you will have to sort() the array:
var len=6,
arr=[''];
for(var i=0;i<len;i++){
for(var k=0,l=arr.length;k<l;k++){
if(getNum1(arr[k])%2===1){
arr[k]+=1;
}else{
if(i<len-1){
arr.push(arr[k]+1);
}
arr[k]+=0;
}
}
}
function getNum1(str){
var n=0;
for(var i=str.length-1;i>=0;i--){
if(str.substr(i,1)==='1'){n++;}
else{break;}
}
return n;
}
document.write(arr.sort().join('<br />'));
See http://jsperf.com/generate-all-combinations-for-pair-of-bits-set-to-1 if you want to compare the performance. It seems that the fastest code is the first one on Chrome but the second one on Firefox.
You can also do this with bit twiddling. If the lowest two bits are zero, we need to set them, which is equivalent to adding 3. Otherwise, we need to replace the lowest block of ones by its top bit and a 1-bit to the left of it. This can be done as follows, where x is the current combination:
x3 = x + 3;
return (((x ^ x3) - 2) >> 2) + x3;

Solving Project Euler 16 with Javascript

I'm working on Project Euler, writing solutions in JavaScript. However, it seems Problem 16 cannot be solved with Javascript:
215 = 32768 and the sum of its digits is 3 + 2 + 7 + 6 + 8 = 26.
What is the sum of the digits of the number 21000?
Because JavaScript's 64bit precision isn't big enough to hold the number, calculating Math.pow(2, 1000) gives 1.0715086071862673e+301. Obviously, I can't use this value to solve the problem because it doesn't contain all the digits of 21000.
Is there another way to solve this problem? Note that I am not asking how to get around the precision issue; however, if that's the only solution, so be it.
Ideally, I'd like to find an alternate solution (maybe a super-epic math approach?) to the problem.
(as an side note, i'm not trying to cheat and wean the answer out of SO. I've solved it, but I had to use Python)
It is possible to solve this by a naive approach of storing 2^1000 in an array (of digits). Runs in less than a second. Original idea from here.
var number = [1],
sum = 0;
for(var i = 0; i < 1000; i++)
{
var overflow = 0,
count = number.length + 1
for(var j = 0; j < count; j++)
{
var digit = number[j] || 0;
digit = 2 * digit + overflow;
if(digit > 9)
{
digit -= 10;
overflow = 1;
}
else
{
overflow = 0;
}
number[j] = digit;
}
}
for(var i = 0; i < 1000; i++)
{
sum += number[i];
}
console.log(sum);
check out a question I asked earlier:
summing exponents in javascript
The response talks about BigNumber in JavaScript. That should help you get around the precision shortfalls in JavaScript when dealing with large numbers.

Categories

Resources