so I want my program to pass an int into the serialport, but javascript makes all numbers floats, that is bad.
even more if i try
sp.write(255)//outputs 0x080000010000000000000000020000
sp.write(256)//outputs infinitely
I hooked it up to a bus pirate so I could check the output
if I convert numbers to a hex string then the serialport sends out the char equivalent of my number, this is also bad.
var hex=(0xFF).toString(8);
sp.write(hex); //out=0x333737 which is 377=>0x0255 oh and not 8 bits...
hex=(0xFF).toString(16);
sp.write(hex); //out=0x6666 which is FF so at least that one makes some sense
hex=0b10101010; // error... binary does work when i run javascript in html though
but it does output asci characters so that i get the proper hex on the other side
ive tried
function hex2a(hexx) {
var hex = hexx.toString();//force conversion
var str = '';
for (var i = 0; i < hex.length; i += 2)
str += String.fromCharCode(parseInt(hex.substr(i, 2), 16));
return str;
}
but for that 0xff=>0x2505
and ive also tried
hex = String.fromCharCode(hex)
which works perfectly up to 127, after that it is 2 bytes with either a 194 or 195 in first byte
I need to be able to send 8 bytes of integer bit data to an arduino.
var buffer = new Buffer([ 8, 6, 7, 5, 3, 0, 9]);
which works for any value between 0 and 255.
thanks to Traktor53 for point out it is a buffer object
and to https://docs.nodejitsu.com/articles/advanced/buffers/how-to-use-buffers
for confirming how to consruct a Buffer
Related
I'm trying to write my own solution for a BFE problem https://bigfrontend.dev/problem/implement-atob
Basically, writing a polyfill for the atob function available in javascript
I tried to understand the base64 encoding/decoding process and came up with the following implementation that works fine for most inputs but some of the test cases are failing
function myAtob(encoded) {
// All base64 charset
const base64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
let temp = ""; // used for storing all characters to binary form
let decoded = "";
for (let i of encoded) {
// converts each encoded character to binary and pads if required
temp += base64.indexOf(i).toString(2).padStart(6, 0);
}
for (let i = 0; i < temp.length; i += 8) {
const num = temp.slice(i, i + 8); // make groups of 8 bits
const ascii = parseInt(num, 2); // convert 8 bits to number
if (ascii > 30 && ascii < 123){
// I used above 'if' for ignoring the unsupported characters
decoded += String.fromCharCode(ascii); // append string equivalent
}
}
return decoded;
}
I tried to debug and I believe it's happening because some unsupported codes or escaped characters are getting part of my output messing up the test cases.
Example when using the window.atob function,
atob("A===") throws error
atob("AA==") returns '\x00'
These are different from what my function returns. Maybe the padding character = is messing up something.
The following are test case results:
Can someone help me with fixing the logic and handling of edge cases?
I seem to not be understanding the Uint32Array. According to what I've read about the Uint8Array I could just feed it a number inside an array (Uint8Array([16]) or Uint8Array([96,56])) and the results are exactly that. However, when I try the same thing for a larger number like Uint32Array([21640]), it seems to truncate it. Where 21640 should equal 5488 in hex, I only get 88. How does this actually work?
Edit: Elaborations
I am also attempting to concatenate several ArrayBuffers together. If I'm not mistaken readAsArrayBuffer produces an Uint8Array, and I am trying to append to that some 32-bit numbers using https://gist.github.com/72lions/4528834
There is so much information and examples on Uint8Array and what little there was on Uint32Array makes me think that one of these 32 would store a value as if it was 4 of the 8.
The largest value of an unsigned 8 bit number is 255. Larger numbers will be truncated or rolled over depending on the os/cpu. If you want to convert a 32 bit numbers in an 8 bit array try something like this.
var number = 21640;
var byte1 = 0xff & number;
var byte2 = 0xff & (number >> 8);
var byte3 = 0xff & (number >> 16);
var byte4 = 0xff & (number >> 24);
var arr1 = Uint8Array([byte1,byte2,byte3,byte4]);
Just reverse the order of the bytes when you create the array depending on if you want little or big endian.
Here is a working example showing 5488 in console
var bigNumber = new Uint32Array([21640]);
console.log(bigNumber[0].toString(16));
Since you've added more to the question. If you wanted to convert
var byte1 = 0x88;
var byte2 = 0x54;
var byte3 = 0;
var byte4 = 0;
var bigValue = (byte4 << 24) | (byte3 << 16) | (byte2 << 8) | (byte1);
console.log(bigValue);
Although you will need to factor in Endianness
I have a few scientists for clients and they have some problems with how toPrecision is rounding in JavaScript. They want everything rounded to a MAX of 3 sig figs which works most of the time but let me give a few examples of what they want:
Lab value to rounded value
123.5 to 124
1234 to 1230
12.0 to 12.0
0.003 to 0.003
So in other words round things with more than 3 sig figs down to 3. If something has 1 or 2 sig figs DONT append a zero (as that implies the lab was more accurate then they really were) but also in the case of 12.0 DONT remove the zero (as that implies the lab is less accurate then they really were)
Using toPrecision works for all examples given except for the 12.0 to 12.0 example:
var nums = [123.5, 1234, 12.0, 0.003]
var out = nums.map(num => parseFloat(num.toPrecision(3)))
// => [124, 1230, 12, 0.003]
It rounds numbers with more than 3 sig figs to 3, but if you use a number with a .0 or .00 on the end it fails. The reason for this is that the JavaScript engine equates 1.00 to 1, and 12.0 to 12, so the problem is actually not toPrecision, but rather JavaScript itself.
To work around this, what you can do is input numbers as strings, and use toPrecision if there isn't a decimal zero, otherwise operate on the string itself:
var nums = ['123.5', '1234', '12.0', '0.003', '1.000', '1236.00'];
var out = nums.map(str => {
if (/\.0+$/.test(str)) { // test if it ends with .0 or .00, etc.
// use alternative string method:
var zeros = str.match(/[0]+$/)[0].length; // count the no. of trailing zeros
var sigfigs = parseFloat(str).toString().length; // no. of other sig figs
var zerosNeeded = 3 - sigfigs;
if (zerosNeeded < 0) {
return parseFloat(parseFloat(str).toPrecision(3)).toFixed();
} else {
return str.substring(0, sigfigs + 1 + zerosNeeded); // +1 for the decimal point
}
} else {console.log(str)
return parseFloat(parseFloat(str).toPrecision(3)).toString()
}
});
// => ["124", "1230", "12.0", "0.003", "1.00", "1240"]
This works, however as the result must be in a string format if you need to work with floating point numbers and similar, I'd recommend using a different language such as Python. Anyway, I hope this helps!
All you need to do is to write a custom parser.
See this example:
const data = [123.5, 1234, 12.0, 0.003, 100.0, 1.0];
data.forEach(n => {
const result = customToPrecision(n, 3);
console.log(`${n} -> ${result}`);
});
function customToPrecision(number, precision){
let result = number.toPrecision(precision);
// Check if original number is a float
if (number % 1 !== 0){
result = result
.replace(/0+$/, '') // Remove trailing zeros
.replace(/\.$/, '.0'); // Add one zero to incomplete decimal
}
return result;
}
I want to get a random double number (for example 4.58)
and put its digits to three variables - 4 to the first variable, 5 to the second variable and 8 to the third variable.
Not sure why you need this to be a floating-point number. Just create a three-digit number, convert it to a string, and split it into an array.
var numArr = (Math.floor(Math.random() * 900) + 100).toString().split('');
You can get at the numbers using the normal array method: numArr[0] etc.
To convert it to number, add a period in the first array position and then join it back to together:
numArr.splice(1, 0, '.');
var number = numArr.join('');
DEMO
Alternatively, see this SO question on how to create random floating-point numbers.
You could do something like this:
var number = 4.26; // Your generated double number
output = []; // Array to store each digit
sNumber = number.toString(); // Convert the double to a string so we can split it
for (var i = 0, len = sNumber.length; i < len; i += 1)
{
output.push(+sNumber.charAt(i));
}
console.log(output);
The output will be:
4, 2, 6
All numbers in JavaScript are doubles: that is, they are stored as 64-bit IEEE-754 doubles.
That is, the goal is not to get a "double": the goal is to get the string reprsentation of a number formatted as "YYY.XX". For that, consider Number.toFixed, for instance:
(100).toFixed(2)
The result is the string (not a "double"!) "100.00". The parenthesis are required to avoid a grammar ambiguity in this case (it could also have been written as 100.0.toFixed or 100..toFixed), but would not be required if 100 was in a variable.
Use this. I use .replace(/[.]/g,"") for removing ".".
http://jsfiddle.net/sherali/coyv3erf/2/
var randomNumber = Math.floor(Math.random() * 900) + 100;
numArr= randomNumber.toString().replace(/[.]/g,"").split("")
var number = numArr.join("");
console.log(numArr, number); // ["8", "4", "5"] 845
I have a H/W device that normally uses a serial port for an interface, sending and receiving binary messages to a PC UI program. I've added an Ethernet port and small TCP/IP stack with a small web server that I want to use to replace the serial port UI with a web browser UI.
The messages are mostly request/response sort of things, but for some web pages I may need to Tx/Rx two or more messages to get all the info I need for the page. I'll use the AJAX XMLHttpRequest() to send the messages and get the responses for a page.
The H/W device has limited resources (CPU & RAM) so to keep it simple on that end I want to just make a little CGI interface that takes outgoing messages and encodes them as HEX ASCII (i.e. two HEX ASCII chars/byte) to send to the browser which will use some java script to pick apart the messages into fields and convert them to numeric vars and display them to the user. Same for messages sent from the browser to the H/W device.
Messages contain a mixture of field types, signed & unsigned bytes, shorts, longs, floats, and are futher complicated by being mostly in little endian byte order in the messages.
I can handle the H/W end code, but I'm struggling to learn java script and could use help with a function to translate the HEX ASCII <-> numerics on the browser end.
Any ideas? Any example code some where?
Thanks,
Paul
Sounds like you want parseInt. It takes a string and an optional radix (which should always be supplied), and parses the number as an integer in that radix (or a radix based on the format of the number if none is supplied, which is why you should always supply one; people are surprised to find that parseInt("010") returns 8).
> parseInt("ab", 16)
171
To convert back to hex, you can use toString:
> var num = 16
> num.toString(16)
"10"
Note that you will have to pad it out to two characters yourself if it comes out as only a single character:
> num = 5
> num.toString(16)
"5"
I was bored, so I wrote some functions to do the conversion in both directions for you:
function parseHexString(str) {
var result = [];
// Ignore any trailing single digit; I don't know what your needs
// are for this case, so you may want to throw an error or convert
// the lone digit depending on your needs.
while (str.length >= 2) {
result.push(parseInt(str.substring(0, 2), 16));
str = str.substring(2, str.length);
}
return result;
}
function createHexString(arr) {
var result = "";
for (i in arr) {
var str = arr[i].toString(16);
// Pad to two digits, truncate to last two if too long. Again,
// I'm not sure what your needs are for the case, you may want
// to handle errors in some other way.
str = str.length == 0 ? "00" :
str.length == 1 ? "0" + str :
str.length == 2 ? str :
str.substring(str.length-2, str.length);
result += str;
}
return result;
}
Which can be used as follows:
> parseHexString("abcd100001")
[171, 205, 16, 0, 1]
> createHexString([0, 1, 2, 10, 20, 100, 200, 255, 1000, 2000])
"0001020a1464c8ffe8d0"
> parseHexString(createHexString([0, 1, 2, 10, 20, 100, 200, 255, 1000, 2000]))
[0, 1, 2, 10, 20, 100, 200, 255, 232, 208]
You're looking for the parseInt() function:
x = "0xff";
y = parseInt(x, 16);
alert(y); //255
did you looking for something like these 2 functions ?
<html>
<head>
<script type="text/javascript">
function hex2Decimal( hex )
{
return parseInt("0x"+hex);
}
function decimal2Hex( num )
{
return num.toString(16);
}
</script>
</head>
<body>
<script type="text/javascript">
document.write(hex2Decimal("A") + "<br />");
document.write(decimal2Hex(16) + "<br />");
</script>
</body>
</html>