Why isn't my negative number properly obtained in NodeJS? - javascript

I am using nodeJS to parse some HEX string, I am trying to convert the HEX value into a integer value using parseInt but I am running into some difficulties with the negative number that I don't understand the reason why.
I have the following HEX string D3FFBDFFF900 that is ecoding the following integers x:-0.45*100 y:-0.67*100 z:2.49*100 in the this way
D3FF | BDFF | F900 => -0.45*100 | -0.64*100 | 2.49*100
And I have created the following code snippet ( and I do now that the division by 100 is being missed there )
var x = "D3FFBDFFF900".substring(0,4);
var y = "D3FFBDFFF900".substring(4,8);
var z = "D3FFBDFFF900".substring(8);
console.log("x:"+x);
console.log("y:"+y);
console.log("z:"+z);
console.log("parseInt x "+parseInt(x.toString(16),16));
console.log("parseInt y "+parseInt(y.toString(16),16));
console.log("parseInt z "+parseInt(z.toString(16),16));
Why isn't parseInt been able to decode at least the values x=-45, y=-67 and z=249 and instead I have the above output?
Thanks in advance,
EDIT: the way of encoding the data is like below, where the print just print the original HEX string into a serial bus
#define NIBBLE_TO_HEX_CHAR(i) ((i <= 9) ? ('0' + i) : ('A' - 10 + i))
#define HIGH_NIBBLE(i) ((i >> 4) & 0x0F)
#define LOW_NIBBLE(i) (i & 0x0F)
for (int i = 0; i < size; ++i) {
print(static_cast<char>(NIBBLE_TO_HEX_CHAR(HIGH_NIBBLE(payload[i]))));
print(static_cast<char>(NIBBLE_TO_HEX_CHAR(LOW_NIBBLE(payload[i]))));
}
and the values x,y,z are got as below where type of accelerometer.getX() -> double
x = (int16_t)(accelerometer.getX()*100)
y = (int16_t)(accelerometer.getX()*100)
z = (int16_t)(accelerometer.getX()*100)

How should the parser know, that you swapped the nibbles and use hex with 4 digits?
0xD3FF = 15 * 1 + 15 * 16 + 3 * 256 + 13 * 4096 = 54271
-45 = -0x2D
-67 = -0x43
249 = 0xF9
The parser does a correct job.
To parse the received hex values you have to swap the high and low nibbles:
D3FF => FFD3
Next you have to parse the hex to dec. If your value >= 0x8000 you have to invert the binary representation and add 1
0xFFD3 = 65491 > 0x8000 = 32768
-(~65491 & 0xFFFF) + 1 = -43

Related

Algorith problem Decode Hex to set output

I got an algorithm that I need to solve. Unfortunately, I can't even find a clue about a solution. Please help me to understand how to solve this problem.
The problem
An imaginary pen input device sends hex data to the device to display a line with color.
Examples Draw simple Green Line
Set color to green, draw a line from (0,0) to (4000, 4000). Filled circle in this diagram indicates a pen down
position, empty circle indicates pen up position.
Input Data: F0A04000417F4000417FC040004000804001C05F205F20804000
Output: CLR; CO 0 255 0 255; MV (0, 0); PEN DOWN;
MV (4000, 4000); PEN UP;
I got the information about each output.
This code is for encoding hex to binary. I guess that the solution would encode the hex to binary, and manipulate it to set correct output.
function hex2bin(hex){
return (parseInt(hex, 16).toString(2))}
The expected result has the same output as Examaple's with the input data.
First of all, some important information is missing from your question: how the numbers like 4000 (in the result) are encoded in the hex format.
I think I could derive it from the example though
The peculiar numeric encoding
Numbers seem to be encoded with 2 bytes (4 hex characters) each, where the most significant bits of these 2 bytes (bits 7 and 15) do not contribute to the value (they are always zero).
Furthermore, the remaining 14 bits are encoded in offset binary, where the most significant of those 14 bits is the inverted sign bit.
This means that "4000" is zero, "0000" is -8192 (the minimum), and "7F7F" is 8191 (the maximum). Note that the one but last character cannot be more than 7, since that would set a bit that is not used in this (custom) encoding.
This was the hardest part to derive from the little info you provided.
On the Example
The input example you provided can be broken down into pieces like this:
opcode | argument(s)
-------+----------------------------
"F0" |
"A0" | "4000" "417F" "4000" "417F"
"C0" | "4000" "4000"
"80" | "4001"
"C0" | "5F20" "5F20"
"80" | "4000"
Using the numeric conversion discussed above, this would translate to:
opcode | argument(s)
-------+------------
240 |
160 | 0 255 0 255
192 | 0 0
128 | 1
192 | 4000 4000
128 | 0
And then it is a matter of following the instructions to turn that into the required output.
So the algorithm could first decode the input string into commands, where each command consists of an opcode and zero or more numeric arguments.
And then those commands could be turned into the required output by keeping track of whether the pen is down and what the current coordinates are:
function decode(hex) {
let commands = [];
let command;
for (let i = 0, len; i < hex.length; i+=len) {
// Opcodes take 1 byte (i.e. 2 hex characters), and
// numbers take 2 bytes (4 characters)
len = hex[i] >= "8" ? 2 : 4;
let num = parseInt(hex.slice(i, i+len), 16);
if (len === 2) { // opcode
command = []; // start a new command
commands.push(command);
} else { // number
// The encoded format is a custom one. This seems to be it:
num = ((num & 0x7F00) >> 1) + (num & 0x7F) - 0x2000;
}
command.push(num); // push opcode or argument in current command
}
return commands;
}
function disassemble(hex) {
let isPenDown = false;
let x = 0, y = 0;
let output = "";
let commands = decode(hex);
for (let [opcode, ...args] of commands) {
if (opcode === 0xF0) {
x = y = 0;
isPenDown = false;
output += "CLR;\n";
} else if (opcode === 0x80) {
isPenDown = args[0] > 0;
output += "PEN " + (isPenDown ? "DOWN" : "UP") + ";\n";
} else if (opcode === 0xA0) {
output += "CO " + args.join(" ") + ";\n";
} else if (opcode === 0xC0) {
let allPos = "", lastPos;
for (let i = 0; i < args.length; i+=2) {
x += args[i];
y += args[i+1];
lastPos = ` (${x}, ${y})`;
if (isPenDown) allPos += lastPos;
}
output += "MV" + (allPos || lastPos) + ";\n";
} // else: ignore unknown commands
}
return output;
}
// Sample:
console.log(disassemble("F0A04000417F4000417FC040004000804001C05F205F20804000"));
More to do
In the screenshot of the problem, near the end, there is also mention of clipping movements to a bounding box. This goes beyond your question about decoding the hex input, so I will leave it at this. For the interested, you could check out Q&A about calculating line segment intersections, such as this one.

How to split large integer into an array of 8-bit integers

Wondering how to convert the output of arbitrarily sized integers like 1 or 12345 or 5324617851000199519157 to an array of integers.
[1] // for the first one
// [probably just a few values for the second 12345...]
[1, 123, 255, 32, ...] // not sure here...
I am not sure what the resulting value would look like or how to compute it, but somehow it would be something like:
A bunch of 8-bit numbers that can be used to reconstruct (somehow) the original arbitrary integer. I am not sure what calculations would be required to do this either. But all I do know is that each unique arbitrarily-sized integer should result in a unique array of 8-bit values. That is, no two different date integers should result in the same array.
It doesn't matter the language much how this is implemented, but probably an imperative language like JavaScript or C.
I am pretty sure the arrays should all be the same length as well, but if that's not possible then knowing how to do it a different way would be okay.
I'm not sure if this is too brute-forcey for what you want, but you can take an arbitrary string and just do the long division into a unit8Array.
Here's a function (borrowed liberally from here) that will convert back and forth from an arbitrarily long string:
function eightBit(str){
let dec = [...str], sum = []
while(dec.length){
let s = 1 * dec.shift()
for(let i = 0; s || i < sum.length; i++){
s += (sum[i] || 0) * 10
sum[i] = s % 256
s = (s - sum[i]) / 256
}
}
return Uint8Array.from(sum.reverse())
}
function eightBit2String(arr){
var dec = [...arr], sum = []
while(dec.length){
let s = 1 * dec.shift()
for(let i = 0; s || i < sum.length; i++){
s += (sum[i] || 0) * 256
sum[i] = s % 10
s = (s - sum[i]) / 10
}
}
return sum.reverse().join('')
}
// sanity check
console.log("256 = ", eightBit('256'), "258 = ", eightBit('258'))
let n = '47171857151875817758571875815815782572758275672576575677'
let a = eightBit(n)
console.log("to convert:", n)
console.log("converted:", a.toString())
let s = eightBit2String(a)
console.log("converted back:", s)
No doubt, there are some efficiencies to be found (maybe you can avoid the interim arrays).
Most languages, including C and Javascript, have bit-shifting and bit-masking operations as part of their basic math operations. But beware Javascript: numbers are 64 bits, but only 32-bit masking operations are allowed. So:
let bignum = Date.now();
let hi = Math.floor(bignum / 0x100000000),
lo = bignum & 0xFFFFFFFF,
bytes = [
(hi >> 24) & 0xFF,
(hi >> 16) & 0xFF,
(hi >> 8) & 0xFF,
hi & 0xFF,
(lo >> 24) & 0xFF,
(lo >> 16) & 0xFF,
(lo >> 8) & 0xFF,
lo & 0xFF
];

What is the reverse of the Modulo operator

I have hard time wrapping my head around how to get this to work so I came to ask the help of the brilliant minds in here.
The thing is, I want to reverse the process of the below equation so that I get X from the given Y and Z.
Z = [ ( X * 30 ) % Y ]
For the use-case, a user inputs number Y and then presses ENTER, the system get's the current server time and then multiplies that by 30. The user will then be given the remainder of the server time in format HHMMssxxx, (hmm, xxx here is the millisecond.. I don't know the format letter for millisecond.. hehe..), divided by Y - that is (X*30) % Y where X is the current server time converted to int.
How can I do this in reverse?
The catch is, X should not be greater than 2359999 -> (23:59:59.999) the maximum time value for a 24-hour clock.
Supposedly I have Z = 32, Y = 400, how can I find X?
I know that it's possible to have multiple answers. Here's what I came up so far but I think this is not very optimal in terms of performance.
function getTimeIDx(rem, codeIndexer) {
var times = [];
for(var i = 0; i < 2400000; i++) {
if((i * 30) % codeIndexer == rem) {
var str = i.toString(),
l = str.length;
if(l < 9)
str = '000000000'.substr(0, 9 - l) + str;
str = str.substr(0, 2) + ':' + str.substr(2, 2) + ':' + str.substr(4, 2) + '.' + str.substr(6);
if(/^(?:[0-1]?\d|2[0-3]):(?:[0-5]?\d):(?:[0-5]+\d)/.test(str))
times.push(str);
}
}
return times;
}
Is there some way to do this more efficiently? Is there something like a inverse modulo?
EDIT:
Updated code to check if the string is a valid time.
You cannot reverse it. Modulo is the remainder from a division operation.
Simplifying your equation. Z = Y % 2
Z is 0 for half of the values and 1 for the rest.
You can not solve for the dividend with just the remainder and the divisor.
Lets fill it into the equation:
32 = ( X * 30 ) % 400
Then this means that X * 30 is a multiple of 400 plus 32:
32
432
832
...
Now we could divide that by 30 to get x. That could be done in js like this:
function* reverse(Z, Y) {
for(let n = 0; ; n++)
yield (Z + Y * n) / 30;
}
Usable as:
for(let X of reverse(32, 400))
console.log(X);
Note that this loop will run forever as there are infinite results. Try it

whats the meaning of this condition if (buffer[0] & 0x80)

I came across this code below , trying to understand what the meaning of this condition
if (buffer[0] & 0x80)
BigInteger.fromBuffer = function (buffer) {
if (buffer[0] & 0x80) {
var byteArray = Array.prototype.slice.call(buffer)
return new BigInteger([0].concat(byteArray))
}
return new BigInteger(buffer)
}
This is the bitwise and-operator. It does an and-operation on each bit position of these two integers and returns a new integer.
As an example:
10010001
10000000
That would be:
10000000
https://en.wikipedia.org/wiki/Bitwise_operation#AND
x means 0 or 1.
x x x x x x x x
bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0
buffer[0] = xxxx xxxx;
0x80 = 1000 0000;
--------------------- &
buffer[0] = 1xxx xxxx
Its means slice will be execute when buffer[0] = 1xxx xxxx; (bit 7 of buffer[0] must be 1, others bits (bit 0-6) can be 0 or 1).

Converting large integer to 8 byte array in JavaScript

I'm trying to convert a large number into an 8 byte array in javascript.
Here is an IMEI that I am passing in: 45035997012373300
var bytes = new Array(7);
for(var k=0;k<8;k++) {
bytes[k] = value & (255);
value = value / 256;
}
This ends up giving the byte array: 48,47,7,44,0,0,160,0. Converted back to a long, the value is 45035997012373296, which is 4 less than the correct value.
Any idea why this is and how I can fix it to serialize into the correct bytes?
Since you are converting from decimal to bytes, dividing by 256 is an operation that is pretty easily simulated by splitting up a number in a string into parts. There are two mathematical rules that we can take advantage of.
The right-most n digits of a decimal number can determine divisibility by 2^n.
10^n will always be divisible by 2^n.
Thus we can take the number and split off the right-most 8 digits to find the remainder (i.e., & 255), divide the right part by 256, and then also divide the left part of the number by 256 separately. The remainder from the left part can be shifted into the right part of the number (the right-most 8 digits) by the formula n*10^8 \ 256 = (q*256+r)*10^8 \ 256 = q*256*10^8\256 + r*10^8\256 = q*10^8 + r*5^8, where \ is integer division and q and r are quotient and remainder, respectively for n \ 256. This yields the following method to do integer division by 256 for strings of up to 23 digits (15 normal JS precision + 8 extra yielded by this method) in length:
function divide256(n)
{
if (n.length <= 8)
{
return (Math.floor(parseInt(n) / 256)).toString();
}
else
{
var top = n.substring(0, n.length - 8);
var bottom = n.substring(n.length - 8);
var topVal = Math.floor(parseInt(top) / 256);
var bottomVal = Math.floor(parseInt(bottom) / 256);
var rem = (100000000 / 256) * (parseInt(top) % 256);
bottomVal += rem;
topVal += Math.floor(bottomVal / 100000000); // shift back possible carry
bottomVal %= 100000000;
if (topVal == 0) return bottomVal.toString();
else return topVal.toString() + bottomVal.toString();
}
}
Technically this could be implemented to divide an integer of any arbitrary size by 256, simply by recursively breaking the number into 8-digit parts and handling the division of each part separately using the same method.
Here is a working implementation that calculates the correct byte array for your example number (45035997012373300): http://jsfiddle.net/kkX2U/.
[52, 47, 7, 44, 0, 0, 160, 0]
Your value and the largest JavaScript integer compared:
45035997012373300 // Yours
9007199254740992 // JavaScript's biggest integer
JavaScript cannot represent your original value exactly as an integer; that's why your script breaking it down gives you an inexact representation.
Related:
var diff = 45035997012373300 - 45035997012373298;
// 0 (not 2)
Edit: If you can express your number as a hexadecimal string:
function bytesFromHex(str,pad){
if (str.length%2) str="0"+str;
var bytes = str.match(/../g).map(function(s){
return parseInt(s,16);
});
if (pad) for (var i=bytes.length;i<pad;++i) bytes.unshift(0);
return bytes;
}
var imei = "a000002c072f34";
var bytes = bytesFromHex(imei,8);
// [0,160,0,0,44,7,47,52]
If you need the bytes ordered from least-to-most significant, throw a .reverse() on the result.
store the imei as a hex string (if you can), then parse the string in that manner, this way you can keep the precision when you build the array. I will be back with a PoC when i get home on my regular computer, if this question has not been answered.
something like:
function parseHexString(str){
for (var i=0, j=0; i<str.length; i+=2, j++){
array[j] = parseInt("0x"+str.substr(i, 2));
}
}
or close to that whatever...

Categories

Resources