I want to write a function that will encode / decode a string to an int value. The purpose of this is so that I can encrypt text using RSA encryption / decryption methods that I wrote that are limited to only integers.
Basically what I want is something like:
encode("foo bar") // ex output: 488929774
decode(488929774) // ex output: "foo bar"
You approach has major issues, you should encode character by character, instead of trying to encode a numerical representation of the whole string
A string is a sequence of characters, using some character encoding. Characters can be represented with integers, in consequence you would be able to concatenate those integers, and generate an integer that represents the whole string. But the size of that resulting integer would be impossible to handle.
I'm going to expose what would happen if you try to convert a string into its numerical representation ( a sequence of char codes with proper padding )
If you convert each character into its UTF-16 numerical representation using str.charCodeAt(index), which can represent a value from 0 to 65535 (5 digits), you will get Numbers with different length.
Eg: 'a'.charCodeAt(0) = 97 // 2 digits
Eg: 'w'.charCodeAt(0) = 119 // 3 digits
Each character representation needs to have the same length, so has to be converted back to a String, and sometimes prefixed with some padding, using zeroes (0).
Eg : 97 = '00097' // length :5
Eg : 119 = '00119' // length :5
If you concatenate those padded charCodes, you get a long numerical string, that can be converted back to an Integer.
Eg : 'aw' = '0009700119' => Number('0009700119') = 9700119
At this point you should already been able to see the problem you will encounter : Number.MAX_SAFE_INTEGER
Demo implementation : encode() / decode()
Strings longer than 3 chars, will produce unexpected results...
function encode(myString){
let resultStr = '';
for(let i=0; i<myString.length;i++){
let str = String(myString.charCodeAt(i));
for(let a=0;a<5-str.length;a++) resultStr+=0;
resultStr+=str;
}
return Number( resultStr );
}
function decode(myInt){
let myIntStr = String(myInt);
let padding = 5- (myIntStr.length % 5);
for(let i=0; i < padding; i++){
myIntStr = '0' + myIntStr;
}
let chars = myIntStr.match(new RegExp('.{1,'+5+'}(?=(.{'+5+'})+(?!.))|.{1,'+5+'}$', 'g'))
let myStr ='';
for(let i=0; i < chars.length; i++){
myStr += String.fromCharCode( chars[i] );
}
return myStr;
}
let myString= window.prompt('insert string to encode');
let encoded = encode(myString);
console.log('Encoded:', encoded )
let decoded = decode(encoded);
console.log('Decoded:', decoded)
The longer gets the String, the bigger gets the resulting integer. And you will fast reach the maximum numeric value representable in JavaScript.
Related
I'm receiving some data which I need to turn them to numbers, make some computation with that and then I need to use the same data in another place but as a string.
I'm using parseFloat() but the problem is that it already removes the letters part of that number.
const string = parseFloat("100 MB")
console.log(string) // 100
Is there something else other than parseFloat() to turn a string into a number but somehow keep the MB part of the string if I want to turn it back as the original string?
const string = "100 MB";
let toArr = string.split(' ');
// do your math computation
let num = parseFloat(toArr[0]) * 10.25 + 1.14; // whatever
let result = ''.concat(num, ' ', toArr[1]);
console.log(result);
I have a string in representation of ASCII decimal stored in a column in my db:
[104 105]
this converts to hi.
I need to be able to convert my column into string representation.
I know I can use String.fromCharCode(num,...num+1) but it doesn't quite work for me.
I would need to parse and split my db column value [104 105] into two separate vars:
var num1 = 104;
var num2 - 105;
this doesn't work when I have a complex ASCII decimal representation.
Is there a more efficient way to do this? My input would be something like [104 105 243 0 0 255...] which is in ASCII decimal and I need to get the string representation.
You need to parse that string first, by removing the [] characters, splitting at spaces, and converting the array elements to numbers.
let num_string = '[104 105]';
let nums = num_string.replace(/[\[\]]/g, '').split(' ').map(Number);
let string = String.fromCharCode(...nums);
console.log(string);
You can find the codes using match with a regex, and then map and return an array of the converted codes. Just join the array into a string at the end.
function convert(str, re) {
return str.match(/(\d+)/g).map(code => {
return String.fromCharCode(code);
}).join('');
}
console.log(convert('[104 105]'));
console.log(convert('[104 105 243 0 0 255]'));
I'm trying to solve a problem: Given a string made of digits [0-9], return a string where each digit is repeated a number of times equals to its value. I did the repetition of numbers, how next - I don’t know.
function explode(s) {
for (let i=0; i < s.length; i++){
let y = s[i].repeat(s[i]);
console.log(y);
}
}
You were only missing a result string to collect the parts
function explode(input) {
let result = '';
let s = input.toString(); // So that input can also be a number
for (let i=0; i < s.length; i++){
let y = s[i].repeat(s[i]);
result += y;
}
return result;
}
Javascript is good at coercing numbers to string and vice versa but I prefer to make clear when a numerical character is being treated as a number and when it is intended to be a string.
My snippet tests processing of numbers, string representations of numbers, strings having mixtures of number and letter characters, and letter strings.
it makes use of array.split() to for the character array, array.map() to process the characters (including parseInt to formally change the character to a number when used as the argument the string.repeat(), and array.join() to return the desired numeric string after processing:
let number = 6789;
let numberString = "12345";
let badNum = "3bad2Number";
let noNum = "justLetters";
console.log(expandNums(number));
console.log(expandNums(numberString));
console.log(expandNums(badNum));
console.log(expandNums(noNum));
function expandNums(numOrString) {
let numString = numOrString.toString();
let chars = numString.split('');
let processed = chars.map(char => char.repeat(parseInt(char)));
return processed.join('');
} // end function expandNums
The function performs well under all use situations tested, so is unlikely to throw an error if a bad argument is passes. It also does a good job with the mixed letter/number example.
I want to send the string to an encryption function which accepts an array of four (32-bit) integers.
So how to convert string to array of 32 bit integers in javascript and divide it to send it to function?
This smells of homework, but here you go.
Method 1:
Assuming you want to convert four characters in a string to ints, this will work:
// Declare your values.
var myString = "1234";
// Convert your string array to an int array.
var numberArray[myString.length];
for (var i = 0; i < myString.length]; i++)
{
numberArray[i] = int.parseInt(myString[i]);
}
// Call your function.
MyEncryptionFunction(numberArray);
Method 2:
Assuming you want to convert four characters to the numeric values of their chars, this will work:
// Declare your values.
var myString = "1,2,3,4";
// Convert your string array to an int array.
var numberArray[myString.length];
for (var i = 0; i < myString.length]; i++)
{
numberArray[i] = myString.charCodeAt(i);
}
// Call your function.
MyEncryptionFunction(numberArray);
Method 3:
Assuming you want to split a group of four numbers separated by a consistent delimiter, this will work.
// Declare your values.
var splitter = ",";
var myString = "1,2,3,4";
// Convert myString to a string array.
var stringArray[] = myString.split(splitter);
// Convert your string array to an int array.
var numberArray[stringArray.length];
for (var i = 0; i < stringArray.length]; i++)
{
numberArray[i] = int.parseInt(stringArray[i]);
}
// Call your function.
MyEncryptionFunction(numberArray);
Use string.charCodeAt(i), to get the numeric char code of string string at position i. Depending on your used encryption, you can apply an own compression method, to combine multiple char codes (most char codes are far smaller than 32 bits).
Example of separating a string in an array consisting of pairs (4 chars):
var string = "A sstring dum doo foo bar";
var result = [];
string += Array((5-(string.length%4))%5).join(" "); //Adding padding at the end
for(var i=3, len=string.length; i<len; i+=4){
result.push([string.charCodeAt(i-3), string.charCodeAt(i-2),
string.charCodeAt(i-1), string.charCodeAt(i)]);
}
var result ="1fg";
for(i =0; i < result.length; i++){
var chr = result.charAt(i);
var hexval = chr.charCodeAt(chr)
document.write(hexval + " ");
}
This gives NaN 102 103.
Probably because it's treating the "1" as a integer or something like that. Is there a way I can convert the
"1"->string to the correct integer? In this case: 49.
So it will be
49 102 103 instead of NaN 102 103
Cheers,
Timo
The charCodeAt function takes an index, not a string.
When you pass it a string, it will try to convert the string to a number, and use 0 if it couldn't.
Your first iteration calls '1'.charCodeAt('1'). It will parse '1' as a number and try to get the second character code in the string. Since the string only has one character, that's NaN.
Your second iteration calls 'f'.charCodeAt('f'). Since 'f' cannot be parsed as a number, it will be interpreted as 0, which will give you the first character code.
You should write var hexval = result.charCodeAt(i) to get the character code at the given position in the original string.
You can also write var hexval = chr.charCodeAt(0) to get the character code of the single character in the chr string.