Precision of BigInt JavaScript type - javascript

I have such part of code, where s1 is a correct binary number (string, up to 900 characters):
console.log(BigInt('0b' + s1));
console.log(toLong10(s1));
25153017620665555630531113...
25153017620663410729799174...
These two functions give different results. Which of them is more likely to be wrong: does BigInt really lose so much precision or is it more realistic that I have a mistake in my function?
function summarize(a, b)
{
while(b.length < a.length)
b = "0" + b;
while(a.length < b.length)
a = "0" + a;
a = "0" + a;
b = "0" + b;
let extra = 0;
let i = a.length - 1;
let res = "";
while (i >= 0)
{
let tmp = Number(a[i]) + Number(b[i]) + extra;
extra = Math.floor(tmp / 10);
tmp = tmp % 10;
res = tmp.toString() + res;
i--;
}
if (res[0] == '0')
{
res = res.substr(1);
}
return(res);
}
function multiply2(a, b)
{
a = "0" + a;
let res = "";
let extra = 0;
for (let i = a.length - 1; i >= 0; i--)
{
let tmp = b * a[i] + extra;
extra = Math.floor(tmp / 10);
tmp = tmp % 10;
res = tmp.toString() + res;
}
if (res[0] == '0')
{
res = res.substr(1);
}
return(res);
}
function multiply(a, b)
{
let res = "0";
if (b.length > a.length)
{
let c = a;
a = b;
b = c;
}
let extra0 = "";
for (let i = b.length - 1; i >= 0; i--)
{
res = summarize(res, multiply2(a, b[i]) + extra0);
extra0 = extra0 + "0";
}
if (res[0] == '0')
{
res = res.substr(1);
}
return(res);
}
function toPower(num, power)
{
let res = "1";
if (power == 0)
return(res);
res = toPower(num, Math.floor(power / 2));
if (power % 2 == 0)
return(multiply(res, res));
else
return(multiply(multiply(res, res), num));
}
function toLong10(a)
{
a = a.split("").reverse().join("");
let res = "0";
let power = 0;
for (let i = 0; i < a.length; i++)
{
res = summarize(res, multiply(a[i], toPower("2", power)));
power++;
}
return(res);
}

Related

Longest Common Substring (more than 2 arguments)

I have seen the solution for LCS 2 strings. Below is the code.
I am curious how can I change it so that it can solve properly when more than 2 strings are given.
I would appreciate any help or resource that can be useful
Thank you.
const printLCS = (a, b) => {
let m = a.length;
let n = b.length;
let lcs = new Array(m + 1);
let lcsLen = 0;
let row = 0, col = 0;
for (let i = 0; i <= m; i++) {
lcs[i] = Array(n + 1);
for (let j = 0; j <= n; j++) {
lcs[i][j] = 0;
if (i == 0 || j == 0) {
lcs[i][j] = 0;
} else if (a[i - 1] == b[j - 1]) {
lcs[i][j] = lcs[i - 1][j - 1] + 1;
if (lcsLen < lcs[i][j]) {
lcsLen = lcs[i][j];
row = i;
col = j;
}
} else {
lcs[i][j] = 0;
}
}
}
if (lcsLen == 0) {
console.log("No Common Substring");
return;
}
let resStr = "";
while (lcs[row][col] != 0) {
resStr = a[row - 1] + resStr;
--lcsLen;
row--;
col--;
}
console.log(resStr);
}
const myArgs = process.argv.slice(2);
printLCS(myArgs[0], myArgs[1]);
const onErr = (err) => {
console.log(err);
return 1;
}
Although, it might be a bit too late to answer now, I think, I might have found the issue you have.
It is with the function call.
printLCS(myArgs[0],myArgs[1]);
You are specifying the third and fourth argument, while perhaps a better way would be to spread it all like this.
printLCS(...myArgs);

What is the difference between javascript and python Fibonacci code here?

I'm currently using matrix multiplication formulas to create algorithms for Fibonacci sequences.
I made my JavaScript code based on the following python code. However, it was confirmed that another value was output [case fib(150)]. I think the % mod is wrong, but how can I solve this problem?
javascript code
const n = parseInt(prompt("Number"));
const mod = 1000000007;
const fib = () => {
const zero = [
[1, 1],
[1, 0],
];
const base = [
[1],
[1]
];
const power = (a, num) => {
if (num === 1) return a;
else if (num % 2 != 0) return multi(power(a, num - 1), a);
else return power(multi(a, a), parseInt(num / 2));
};
const multi = (a, b) => {
const temp = Array.from(Array(2), () => Array(b[0].length).fill(0));
for (let i = 0; i < 2; i++) {
for (let j = 0; j < b[0].length; j++) {
let sum_num = 0;
for (let k = 0; k < 2; k++) {
sum_num += a[i][k] * b[k][j];
}
temp[i][j] = sum_num % mod;
}
}
return temp;
};
return multi(power(zero, n - 2), base)[0][0];
};
if (n === 0) {
console.log(0);
} else if (n < 3) {
console.log(1);
} else {
console.log(fib());
}
python code
import sys
input = sys.stdin.readline
MOD = 1000000007
adj=[[1,1],[1,0]]
start=[[1],[1]]
N = int(input())
def power(adj,n):
if n == 1:
return adj
elif n % 2:
return multi(power(adj,n-1), adj)
else:
return power(multi(adj,adj), n//2)
def multi(a,b):
temp=[[0]*len(b[0]) for _ in range(2)]
for i in range(2):
for j in range(len(b[0])):
sum_n = 0
for k in range(2):
sum_n += a[i][k]*b[k][j]
temp[i][j]= sum_n % MOD
return temp
if N < 3:
print(1)
else:
print(multi(power(adj,N-2),start)[0][0])
I solved it using bigint. Thank you for your help. (mplungjan, Kelly Bundy)
const n = BigInt(prompt('Number'));
const mod = 1000000007n;
const fib = () => {
const zero = [
[1n, 1n],
[1n, 0n],
];
const base = [[1n], [1n]];
const power = (a, num) => {
if (num === 1n) return a;
else if (num % 2n != 0) return multi(power(a, num - 1n), a);
else return power(multi(a, a), BigInt(num / 2n));
};
const multi = (a, b) => {
const temp = Array.from(Array(2), () => Array(b[0].length).fill(0));
for (let i = 0; i < 2; i++) {
for (let j = 0; j < b[0].length; j++) {
let sum_num = 0n;
for (let k = 0; k < 2; k++) {
sum_num += a[i][k] * b[k][j];
}
temp[i][j] = sum_num % mod;
}
}
return temp;
};
return multi(power(zero, n - 2n), base)[0][0];
};
if (n === 0) {
console.log(0);
} else if (n < 3) {
console.log(1);
} else {
console.log(parseInt(fib()));
}

CodeWars sorting numbers and letters

I am currently doing a codewars problem, and I think I almost got it however, I ran across a problem when sorting index values with the same letter. link to problem is here. https://www.codewars.com/kata/5782dd86202c0e43410001f6
function doMath(s) {
let strSplit = s.split(' ');
let clonedArr = strSplit.slice();
for (let i = 0; i < strSplit.length; i++) {
for (let j = 0; j < strSplit[i].length; j++) {
let current = strSplit[i][j];
if (isNaN(current)) {
let letter = current;
strSplit[i] = strSplit[i].replace(letter, '');
strSplit[i] = letter + strSplit[i];
}
}
}
let sortedArr = strSplit.sort();
console.log(sortedArr);
// ["b900", "y369", "z123", "z246", "z89"]
let noLetterArr = sortedArr.map(x => {
return x.slice(1);
});
let numberArr = noLetterArr.map(y => {
return +y;
})
let firstEl = numberArr[0];
for (let i = 1; i < numberArr.length; i++) {
if (numberArr.indexOf(numberArr[i]) % 4 == 1) {
firstEl += numberArr[i];
}
if (numberArr.indexOf(numberArr[i]) % 4 == 2) {
firstEl -= numberArr[i];
}
if (numberArr.indexOf(numberArr[i]) % 4 == 3) {
firstEl *= numberArr[i];
}
}
return firstEl;
}
console.log(doMath('24z6 1z23 y369 89z 900b'));
I would like to sort the sortedArr the ones with the same letter by how they first appeared in string. So since "z246" appeared first in the original string. I would like to have that before "1z23". I had a hard time creating a function for that.
var al = [];
function doMath(s) {
var ar = s.split(" ");
for (let i = 0; i < ar.length; i++) {
for (let char of ar[i]) {
let temp = char.match(/[a-z]/i);
if (temp) {
al[i] = char;
ar[i] = ar[i].replace(char, '');
ar[i] = char + ar[i];
}
}
}
al = al.sort();
//New Sort Logic to pass above test case and others too
var n = [];
for (let i = 0; i < al.length; i++) {
for (let j = 0; j < ar.length; j++) {
if (ar[j].startsWith(al[i]) && !n.includes(ar[j])) {
n.push(ar[j]);
}
}
}
var result = parseInt(n[0].substr(1)),
count = 1;
for (let i = 1; i < n.length; i++) {
if (count == 1) {
result = result + parseInt(n[i].substr(1));
count++;
} else if (count == 2) {
result = result - parseInt(n[i].substr(1));
count++;
} else if (count == 3) {
result = result * parseInt(n[i].substr(1));
count++;
} else if (count == 4) {
result = result / parseInt(n[i].substr(1));
count = 1;
}
}
return Math.round(result);
}

Need help sorting array and displaying it on the HTML page

My HW assignment requires me to have a user enter integers and for it to come out on the HTML in sorted array without the sort method. I have this code and it asks the users input but the integers do not come up on page.
<script type="text/javascript">
var arr = [];
function addNum() {
var n = prompt("How many integrs?", "0");
var num = parseInt(n);
for (var i = 0; i < num; i++) {
arr[i] = parseInt(prompt("Enter next integer: ","0"));
}
var outputSorted = document.getElementById('outputSorted');
outputSorted = "";
outputSorted.append("Input array : ");
for (var i = 0; i < num; i++) {
outputSorted.append(arr[i]+" ");
}
bubbleSort(arr);
outputSorted.append("Sorted array : ");
for (var i = 0; i < num; i++) {
outputSorted.append(arr[i]+" ");
}
}
function bubbleSort(a) {
var swapped;
do {
swapped = false;
for (var i=0; i < a.length - 1; i++) {
if (a[i] > a[i+1]) {
var temp = a[i];
a[i] = a[i+1];
a[i+1] = temp;
swapped = true;
}
}
} while (swapped);
}
function searchNum() {
var m = parseInt(prompt("Enter num to be searched: ","0"));
var found = binarySearch(arr, m);
var outputSearch = document.getElementById('outputSearch');
if (found == -1) {
outputSearch.append("Number not found");
} else {
outputSearch.append("Number found at index : " + (found + 1));
}
}
function binarySearch(array, targetValue) {
var min = 0;
var max = array.length - 1;
var guess;
while (min <= max) {
guess = Math.floor((max + min) / 2);
if (array[guess] === targetValue) {
return guess;
}
else if (array[guess] < targetValue) {
min = guess + 1;
}
else {
max = guess - 1;
}
}
return -1;
}
</script>
outputSorted is a DOM element, and append() is not a function of that element. Rather than that, use innerHTML += for each bit you want to add. See below. And note, those are the ONLY changes I made. So your ugly rendered HTML is what it is.
var arr = [];
addNum = function addNum() {
var n = prompt("How many integrs?", "0");
var num = parseInt(n);
for (var i = 0; i < num; i++) {
arr[i] = parseInt(prompt("Enter next integer: ", "0"));
}
var outputSorted = document.getElementById('outputSorted');
outputSorted.innerHTML += "Input array : "
for (var i = 0; i < num; i++) {
outputSorted.innerHTML += arr[i] + " ";
}
bubbleSort(arr);
outputSorted.innerHTML += "Sorted array : ";
for (var i = 0; i < num; i++) {
outputSorted.innerHTML += arr[i] + " ";
}
}
function bubbleSort(a) {
var swapped;
do {
swapped = false;
for (var i = 0; i < a.length - 1; i++) {
if (a[i] > a[i + 1]) {
var temp = a[i];
a[i] = a[i + 1];
a[i + 1] = temp;
swapped = true;
}
}
} while (swapped);
}
function searchNum() {
var m = parseInt(prompt("Enter num to be searched: ", "0"));
var found = binarySearch(arr, m);
var outputSearch = document.getElementById('outputSearch');
if (found == -1) {
outputSearch.innerHTML += ("Number not found");
} else {
outputSearch.innerHTML += ("Number found at index : " + (found + 1));
}
}
function binarySearch(array, targetValue) {
var min = 0;
var max = array.length - 1;
var guess;
while (min <= max) {
guess = Math.floor((max + min) / 2);
if (array[guess] === targetValue) {
return guess;
} else if (array[guess] < targetValue) {
min = guess + 1;
} else {
max = guess - 1;
}
}
return -1;
}
<button onclick="addNum()">
Add some!
</button>
<div id="outputSorted">
</div>
<div id="outputSearch">
</div>

Convert base 10 and base 255 integer strings in JavaScript?

Does anyone know a way to convert base 10 and base 255 strings in JavaScript exceeding the Number.MAX_SAFE_INTEGER value without using a big number library?
For something like:
var base10 = '23456786543234567876543234567876543267';
var base255 = base10ToBase255(base10);
To base-255 or from base-255 as:
var base255 = new Uint8Array(20);
for (var i = 0; i < 20; i++) base255[i] = 254 - i;
var base10 = base255ToBase10(base255);
EDITED: changed to allow for other bases (<=256)
It always boils down to using a big integer, sorry. But you do not need much, it's just about 100 lines of code for what you want (string to base 256 and back).
"use strict";
var COMMON_BASE = 255; // must be 256 at most!
function copyA(a){
var ret = new Uint8Array(a.length);
for(var i = 0;i<a.length;i++){
ret[i] = a[i];
}
return ret;
}
function isZero(a){
for(var i = 0;i<a.length;i++){
if(a[i] !== 0)
return false;
}
return true;
}
function clampA(a){
var alen = a.length;
var i=0;
while(a[alen - 1] === 0)alen--;
var ret = new Uint8Array(alen);
for(var i = 0;i<alen;i++){
ret[i] = a[i];
}
return ret;
}
function addD(a,d) {
var tlen = a.length;
var carry = 0;
var ret = new Uint8Array(tlen +1);
if(d === 0)
return copyA(a);
var i = 0;
var temp = carry;
temp += a[i] + d;
carry = Math.floor(temp / COMMON_BASE);
ret[i] = temp % COMMON_BASE;
for (i = 1; i < tlen; i++) {
temp = carry;
temp += a[i];
carry = Math.floor(temp / COMMON_BASE);
ret[i] = temp % COMMON_BASE;
}
if (carry) {
ret[i] = carry;
}
ret = clampA(ret);
return ret;
};
function mulD(a,d){
var tlen = a.length;
var carry = 0;
var ret = new Uint8Array(tlen + 1);
var k = 0;
var tmp;
if(isZero(a))
return copyA(a);
if(d === 0)
return new Uint8Array(tlen);
for (; k < tlen; k++) {
tmp = a[k] * d + carry;
ret[k] = tmp % COMMON_BASE;
carry = Math.floor(tmp / COMMON_BASE);
}
if (carry) {
ret[k] = carry;
}
ret = clampA(ret);
return ret;
}
function divRem(a,d){
var divrem = function(u, m, v, q, B) {
var k = 0,
t;
for (var j = m - 1; j >= 0; j--) {
k = (k * COMMON_BASE) ;
k += u[j];
if (k >= v) {
t = Math.floor(k / v);
k -= t * v;
} else {
t = 0;
}
q[j] = t;
}
return k;
};
var Q = new Uint8Array(a.length);
var R = divrem(a,a.length, d, Q, 8);
Q = clampA(Q);
return [Q,R];
}
// Assuming 's' being a string with decimal digits
function base10ToBase256(s){
var blen = 0;
// checks&balances omitted
var out = new Uint8Array(1);
for(var i=0;i<s.length;i++){
out = mulD(out,10);
out = addD(out,parseInt(s[i],10) );
}
return out;
}
// Assuming b being a Uint8Array
function base256ToBase10(a){
var s = "";
var t = copyA(a);
var qr = [];
var i = a.length;
while(!isZero(t)){
qr = divRem(t,10);
s = s + qr[1].toString(10);
t = qr[0];
}
return s.split("").reverse().join("");
}
var str = "8716418673416734167345634096788356249857";
//base10ToBase256(str).join(",");
base256ToBase10(base10ToBase256(str));
var str = "8716418673416734167345634096788356249857";
console.log(base10ToBase256(str).join(","));
console.log(base256ToBase10(base10ToBase256(str)));
Here the LSB is at position zero.
It's a rough hack (way too much copies etc.) but it'll do it.

Categories

Resources