夙S溯 发表于 2024-8-26 13:58:13

使用typescript类型体操实现正整数乘法和乘方运算

前置:使用typescript类型系统实现正整数加法运算
https://klpbbs.com/thread-145895-1-1.html
一下使用的部分工具类型定义在此
声明:没有用的东西,没事不要学

由于typescript不能使用+-*/,所以我们需要自定义乘法表
type multiplication_table_key = [
'00','01','02','03','04','05','06','07','08','09','11','12','13','14','15','16','17','18','19','22','23','24','25','26','27','28','29','33','34','35','36','37','38','39','44','45','46','47','48','49','55','56','57','58','59','66','67','68','69','77','78','79','88','89','99'
]

type multiplication_table_value = [
...fill_array<[],10,'0'>,'1','2','3','4','5','6','7','8','9','4','6','8','10','12','14','16','18','9','12','15','18','21','24','27','16','20','24','28','32','36','25','30','35','40','45','36','42','48','54','49','56','63','64','72','81'
]
要计算乘法,不可避免的要进行进位,由于每次进位不再像加法那样最多为1,所以我们需要一个工具类型获取进位:实现
type string_remove_end<s extends string,target extends ''> = isOne<s,get_string_top<s>> extends true ? target : string_remove_end<string_remove_top<s>,`${target}${get_string_top<s>}`>
接着,模仿人类手算,我们要先学会个位乘个位,利用上面的列表,填入两个字符串进行匹配,实现
type multiplication<x extends string,y extends string,index = 0> = multiplication_table_key extends undefined ? undefined : true extends isOne<`${x}${y}`,multiplication_table_key> ? multiplication_table_value : true extends isOne<`${y}${x}`,multiplication_table_key> ? multiplication_table_value : multiplication<x,y,ad<index,1>>
学会了这个,就可以进行个位乘N位的运算了,我们先不处理进位,把每一位相乘的结果存在元组里,实现
type multiplication_x<x extends string,y extends string[],storage extends []> = true extends isOne<y,[]> ? storage : multiplication_x<x,array_remove_end<y>,>
然后,根据这个元组,我们对其进行进位处理,实现
type multiplication_carry<current extends string[],handle extends []> = true extends isOne<current,[]> ? handle : true extends isOne<current['length'],1> ? [...StringToArray<current>,...handle] : multiplication_carry<[...array_remove_end<array_remove_end<current>>,add<get_array_end<array_remove_end<current>>,string_remove_end<get_array_end<current>,''>>],>
他会把['1','12']转化成['2','2']
之后就可以进行多位乘多位的运算了,不过在此之前,我们需要先获取那个位数比较短的,回忆自己列式计算的时候,是不是这样,实现
type min_length_array<x extends any[],y extends any[],storage extends []> = true extends isOne<x],undefined> ? x : true extends isOne<y],undefined> ? y : min_length_array<x,y,>
之后我们遍历短的元组,让他去乘长的元组的所有位,并储存起来,还有,当第二位开始乘时,结果就要补0了,我们模仿的是这个运算
23*123
0369
2460
实现
type multiplications<x extends string[],y extends string[],storage extends []> = true extends isOne<x,[]> ? storage : true extends isOne<y,[]> ? storage : true extends isOne<x,min_length_array<x,y,[]>> ? multiplications<array_remove_end<x>,y,[...storage,[...multiplication_carry<multiplication_x<get_array_end<x>,y,[]>,[]>,...fill_array<[],storage['length'],'0'>]]> : multiplications<array_remove_end<y>,x,[...storage,[...multiplication_carry<multiplication_x<get_array_end<y>,x,[]>,[]>,...fill_array<[],storage['length'],'0'>]]>
最后,我们把他相加,可得最终结果
type multiplication__<a extends string[][],result extends '0'> = true extends isOne<a,[]> ? result : multiplication__<array_remove_end<a>,add<array_to_string<get_array_end<a>,''>,result>>
然后再把元组转化成人能看懂的字符串,一个计算乘法的工具类型就写好了,实现
export type Multiplication<x extends string,y extends string> = multiplication__<multiplications<StringToArray<x>,StringToArray<y>,[]>,'0'>
乘法运算在有了乘法后很简单,不断调用该工具类型就好,实现
type multiplying_power<x extends string,y extends string,times extends string,result extends '1'> = true extends isOne<y,times> ? result : multiplying_power<x,y,add<times,'1'>,Multiplication<result,x>>
type MultiplicationPower<x extends string,y extends string> = multiplying_power<x,y,'1','1'>
效果

页: [1]
查看完整版本: 使用typescript类型体操实现正整数乘法和乘方运算