首页 > 其他分享 >62进制的大数相加

62进制的大数相加

时间:2024-02-26 14:35:17浏览次数:25  
标签:10 const 进制 大数 sum 62 let

1.# 62进制的大数相加

  
// 实现两个62进制数的大数加法
// 输入:两个 62 进制数,String 类型,仅考虑整数
// 输出:两数之和,String 类型
// 62 进制数:按照 1-9,a-z,A-Z 递增

function sum (a, b) {}

不知道你们看到这道题时是什么感受!!!

我当时的想法是:“好像只听过2进制、8进制、16进制、32进制,62进制是什么鬼?

终于在看到这段信息后恍然大悟:62 进制数:按照 1-9,a-z,A-Z 递增

我掰着手加脚指头数了数...

  1. 0 ~ 9 是10个数

  2. a ~ z 是26个字母

  3. A ~ Z 是26个字母

加起来就是62个数,刚好凑齐62进制。

1.1 10进制大数相加(整数)

突然看到求62进制的两数之和,我内心多少是有点懵逼的,懵逼的点在哪?

就是字母咋相加啊?比如 1a(10进制的72) + 2 = 1c(10进制的74)

不过作为接受过9年义务教育的社会主义接班人,一年级咱们就学会了加法(也就是所谓的10进制加法)

回顾一下小学知识: 19 + 23?

1. 个位数相加:9 + 3 = 12。写下 2,进位 1。
  19
+ 23
-----
   2
   
2. 十位数相加并加上进位:1 + 2 + 1(进位)= 4。
  19
+ 23
-----
  42

非常简单是不是?咱们尝试一下用程序来计算两个10进制数的加法。

别担心,朋友,这段代码虽然看起来长了点,但它完全模拟的小学加法,很容易看懂。

敲黑板:10进制的大数相加也是面试的热点

const addBigNumbers = (a, b) => {
  // 从尾部往前计算
  let i = a.length - 1
  let j = b.length - 1
  // 进位标志,1或者0
  let carry = 0
  let result = ''

  while (i >= 0 || j >= 0 || carry) {
    const n1 = +(a[ i ] || 0)
    const n2 = +(b[ j ] || 0)
    // 当前位相加(包含进位部分)
    let sum = n1 + n2 + carry
    // 当前位相加如果>=10,说明要往前进1,否则要重置进位标志
    if (sum >= 10) {
      sum -= 10
      carry = 1
    } else {
      carry = 0
    }
    // 递减往前算
    i--
    j--
    // 当前位 + 前面低位的结果
    result = sum + '' + result
  }

  return result
}

console.log(addBigNumbers('19', '23')) // 42
console.log(addBigNumbers('100', '1024')) // 1124

1.2# 62进制与10进制之间如何转换?

其实咱们知道如何实现10进制大数相加之后,62进制的大数相加也就完成了一大半,只要解决这2个问题,面试官就该给你过了。

  1. 62进制转化为10进制

  2. 10进制转化为62进制

想想只要能将62进制转化为10进制进行相加,再把结果转化为62进制,问题不就迎刃而解了吗?

1a (10进制的72) + 2 = 1c (10进制的74)   

1.3# 62进制转化为10进制

让我们一起来回顾一下计算机基础知识:62进制转化为10进制的规则

设 62 进制数为 d[n]d[n-1]...d[1]d[0],其中 d[i] 表示第 i 位的数字(从右向左,最低位为0)。

则该数的十进制值为:

d[0] * 62^0 + d[1] * 62^1 + ... + d[n] * 62^n

举个例子

const base62ToDecimal = (str) => {
  const base = 62
  const digits = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
  let len = str.length
  let sum = 0
  let n =0 // 最后一位是0,倒数第二位是1...

  while (len--) {
    let digit = digits.indexOf(str[ len ]) // 获取当前位的10进制数,例如a表示10进制的10,b表示11,c表示12...
    sum += digit * Math.pow(base, n)
    n++
  }

  return sum
}

// 示例
console.log(base62ToDecimal('1a')) // 72
console.log(base62ToDecimal('1c')) // 74

有了这个规律用代码实现就很方便了.

const base62ToDecimal = (str) => {
  const base = 62
  const digits = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
  let len = str.length
  let sum = 0
  let n =0 // 最后一位是0,倒数第二位是1...

  while (len--) {
    let digit = digits.indexOf(str[ len ]) // 获取当前位的10进制数,例如a表示10进制的10,b表示11,c表示12...
    sum += digit * Math.pow(base, n)
    n++
  }

  return sum
}

// 示例
console.log(base62ToDecimal('1a')) // 72
console.log(base62ToDecimal('1c')) // 74

1.4# 10进制转化为62进制

同样 10进制转化为62进制也有规律可言:

  1. 用输入的十进制数除以 62,得到商和余数。

  2. 将余数对应的 62 进制字符放在结果的最低位。

  3. 将商作为新的输入,重复步骤 1 和 2,直到商为 0。

  4. 将得到的所有余数按照逆序排列,就是最终的 62 进制表示。

举个例子: 将10进制的72转化为64进制是啥?

   第一步,将 72 不断除以 62,得到的余数就是 62 进制数的低位数字。依次计算如下:

1. 72 ÷ 62 = 1 ... 10 (余数为 10,10对应的62进制字符为 'a')
2. 1 ÷ 62 = 0 ... 1 (余数为 1,1对应的62进制字符为 '1')

第二步,将每次得到的余数按照逆序排列,就是最终的62进制表示:

72(10进制)= '1a'(62进制)

根据规律聪明的你也能很快用程序来实现10进制到62进制的转换

const decimalToBase62 = (decimal) => {
  const base = 62
  const digits = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
  let result = []

  while (decimal > 0) {
    const remainder = decimal % base // 取余

    result.push(digits[ remainder ]) // 将余数真正对应62进制字符存入数组

    decimal = Math.floor(decimal / base) // 计算商,用于下次计算
  }

  return result.reverse().join('') || '0' // 反转结果
}

console.log(decimalToBase62('72')) // 1a
console.log(decimalToBase62('74')) // 1c

1.5 解题啦!!!

啰嗦了这么多,大家有没有发现解决62进制大数相加所需的知识点实在是太基础了

  1. 会小学加法

  2. 会进制转换

最后请丢出这份代码,亮瞎面试官的眼吧!!!

// 62进制转10进制
const base62ToDecimal = (str) => {
  const base = 62
  const digits = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
  let len = str.length
  let sum = 0
  let n =0 // 最后一位是0,倒数第二位是1...

  while (len--) {
    let digit = digits.indexOf(str[ len ]) // 获取当前位的10进制数,例如a表示10进制的10,b表示11,c表示12...
    sum += digit * Math.pow(base, n)
    n++
  }

  return sum
}
// 10进制转62进制
const decimalToBase62 = (decimal) => {
  const base = 62
  const digits = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
  let result = []

  while (decimal > 0) {
    const remainder = decimal % base // 取余

    result.push(digits[ remainder ]) // 将余数真正对应62进制字符存入数组

    decimal = Math.floor(decimal / base) // 计算商,用于下次计算
  }

  return result.reverse().join('') || '0' // 反转结果
}


const addBigBase62Numbers = (a, b) => {
  // 转化为10进制的字符串
  a = '' + base62ToDecimal(a)
  b = '' + base62ToDecimal(b)

  // 从尾部往前计算
  let i = a.length - 1
  let j = b.length - 1
  // 进位标志,1或者0
  let carry = 0
  let result = ''

  while (i >= 0 || j >= 0 || carry) {
    const n1 = +(a[ i ] || 0)
    const n2 = +(b[ j ] || 0)
    // 当前位相加(包含进位部分)
    let sum = n1 + n2 + carry
    // 当前位相加如果>=10,说明要往前进1,否则要重置进位标志
    if (sum >= 10) {
      sum -= 10
      carry = 1
    } else {
      carry = 0
    }
    // 递减往前算
    i--
    j--
    // 当前位 + 前面的
    result = sum + '' + result
  }

  return decimalToBase62(result) // 将10进制再转化为62进制
}

console.log(addBigBase62Numbers('1a', '2')) // 1c
console.log(addBigBase62Numbers('Z', '1')) // 10

2.# 另一种解法

咱们废了老大劲,写了一大坨的代码才实现这个功能,有没有其他更简便一点的解法呢?

其实62进制的数学性质和10进制类似,只是基数(62)不同而已,在10进制中是逢十进一,62进制中就是逢62进一了。所以在我们知道10进制的大数相加如何解之后,仅仅需要做少量的修改就可以变成62进制的大数相加。

搞起!!!

const addBigBase62Numbers = (a, b) => {
  const digits = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
  let i = a.length - 1
  let j = b.length - 1
  let carry = 0
  let result = ''

  while (i >= 0 || j >= 0 || carry) {
    const n1 = digits.indexOf(a[i] || 0) // 获取当前位的10进制表示,如a表示10,b表示11 
    const n2 = digits.indexOf(b[j] || 0) // 获取当前位的10进制表示,如a表示10,b表示11 
    let sum = n1 + n2 + carry
    // 62进1
    if (sum >= 62) {
      sum -= 62
      carry = 1
    } else {
      carry = 0
    }
    // digits[sum] 将当前位转换回62进制
    result = digits[sum] + result

    i--
    j--
  }

  return result
}


console.log(addBigBase62Numbers('1a', '2')) // 1c
console.log(addBigBase62Numbers('Z', '1')) // 10

好舒畅、代码一下子少了一大坨,又可以和面试官吹牛逼了...

3.# 举一反三

文中我们只处理了整数的62进制大数相加,聪明你可以尝试一下这几种场景

  1. 带小数的62进制大数相加?

  2. n进制的大数相加?

原理都是类似的,期待你在评论区写下你的答案,一起交流。

标签:10,const,进制,大数,sum,62,let
From: https://www.cnblogs.com/ygunoil/p/18034248

相关文章

  • P1462 通往奥格瑞玛的道路
    原题传送门思路首先通过读题可以发现两个量分别是血量和金钱,血量当然是越多越好,而金钱确实要最多的一次最少,一般题目说让一个量最多的时候最少,或最少的时候最多,那就会用二分来枚举这个量。那么这一题我们就会选择二分金钱,二分的条件就是到达终点的是的血量有没有大于总血量,也就......
  • 数据可视化是如何在大数据时代为我们服务的?
    在大数据时代的浪潮中,数据可视化如一位巧夺天工的画师,为我们描绘出庞大而丰富的信息画卷,为我们提供了直观、清晰、高效的数据呈现方式。下面我就以可视化从业者的角度,来简单聊聊这个话题。数据可视化首先在信息管理和理解方面展现了其强大的作用。大数据时代,海量的数据如潮水般......
  • Educational Codeforces Round 162 (Rated for Div. 2)
    目录写在前面ABCDE写在最后写在前面比赛地址:https://codeforces.com/contest/1923。为唐氏儿的寒假带来了一个构式的结局,飞舞一个。天使骚骚不太行啊妈的,推了三条线了感觉剧情太白开水了,咖啡馆也是这个熊样子、、、A签到。显然最优的策略是不断地选择最右侧的1进行操作,每......
  • 第二章 二进制
    二进制可以表示计算机信息,是由于IC的一个引脚只能表示两种状态(决定计算机的信息数据只能由二进制数来处理)二进制数的倍数一般是8的倍数,八位二进制数被称为一个字节(字节是最基本的信息计量单位)。对于字节处理数据时还需要关注一些点:比如数据小于储存数据的字节数,那么高位上就用零填......
  • Educational Codeforces Round 162 (Rated for Div. 2)
    EducationalCodeforcesRound162(RatedforDiv.2)A-MovingChips解题思路:模拟一下,不难发现是\(1\)之间\(0\)的个数。代码:#include<bits/stdc++.h>usingnamespacestd;usingll=longlong;usingpii=pair<ll,ll>;#definefifirst#definesesecondusin......
  • P9562 [SDCPC2023] G-Matching 题解
    题目描述给定长度为\(n\)的整数序列\(a_1,a_2,\cdots,a_n\),我们将从该序列中构造出一张无向图\(G\)。具体来说,对于所有\(1\lei<j\len\),若\(i-j=a_i-a_j\),则\(G\)中将存在一条连接节点\(i\)与\(j\)的无向边,其边权为\((a_i+a_j)\)。求\(G\)的一个......
  • Educational Codeforces Round 162 (Rated for Div. 2)
    不会F的场。A答案是最左的\(1\)和最右的\(1\)之间的\(0\)的个数。Code#include<bits/stdc++.h>usingnamespacestd;usingll=longlong;intmain(){ ios::sync_with_stdio(false); cin.tie(0); intt; cin>>t; while(t--){ intn; cin>>n......
  • Educational Codeforces Round 162 [Rated for Div. 2]
    第二次,三道题,剩下的回学校再补,总结:还是需要多练习A:让数列里所有的1都挨在一起,可以看出,相邻1之间有多少个0就需要操作几次,特判:当只有一个1或者原本全是1就输出0;voidsolve(){cin>>n;inttop1=0,top2=0,cnt=0;memset(a,0,sizeof(a));memset(b,0,siz......
  • C# 的浮点类型 float double 和十进制类型 decimal
    //浮点型数据floatdouble(双精度)//floatf=1.1;//ps:写小数的时候只要后面没有加上f/F默认是double类型//正确的定义doubled=1.1;floatf=1.1F;floatf1=1f;//f=d;//ps......
  • [数据管理] 数据治理/大数据平台-开源软件与框架篇
    数据治理可以有效保障数据建设过程在一个合理高效的监管体系下进行,最终提供高质量、安全、流程可追溯的业务数据。1序:数据治理体系企业数据治理体系包括元数据管理、主数据管理、数据资产管理、数据质量管理、数据安全及数据标准等内容。2最新一代数据治理开源软件2.0一站......