突然想到,这种有没有好的思路实现啊 ?
1
fengjianxinghun 2023-06-11 18:04:01 +08:00 1
eval("1+2")
|
2
ellermister OP @fengjianxinghun 不算,这个太变态了
|
3
Mohanson 2023-06-11 18:17:58 +08:00
先实现半加器, 再使用半加器实现全加器, 这样你就实现了加法.
有了加法就有了减法. 有了加法就有了乘法. 有了加, 减, 乘就能实现除法. |
4
2113ic 2023-06-11 19:02:50 +08:00
@ellermister new function('exp', 'return exp')😂
|
5
vituralfuture 2023-06-11 19:42:20 +08:00 2
转补码,用逻辑运算实现一个全加器,然后级联做成 32 位全加器,这样就有了做加减法的能力,乘除法同理,计算出的结果可以转回原码再求出真值
不过如何实现真值到原码到补码?很简单,利用按位逻辑运算,比如 C++中,一条语句`x=1;`,那么 x 就对应内存中一个存储位置,可以用按位逻辑运算取出每一位,然而非常巧的是,内存中的数值是以补码形式存储的,所以就能够取出补码每一位,也就是说不需要求补码,补码已经躺在内存里了 我写了一个程序来简单说明,只有循环用到了加法`i++`,但是所有循环的次数都是确定的,也就是说**循环可以展开,替换成循环体重复 32 次,相当于没有使用加法** ``` #include <iostream> using namespace std; void getComplementCode(bool arr[32], int num) { int mask = 1; for (int i = 0; i < 32; i++) { arr[i] = num & mask; num = num >> 1; } } int getTrueValue(const bool arr[32]){ int s = 0; for (int i = 0; i < 32; i++) { s = s | (arr[i] << i); } return s; } void add1(bool a, bool b, bool &s, bool c0, bool &c1) { s = a ^ b ^ c0; c1 = (a && b) || ((a ^ b) && c0); } void add32(bool a[32], bool b[32], bool s[32], bool c = false) { bool carray[32]; add1(a[0], b[0], s[0], c, carray[0]); for (int i = 1; i < 32; i++) { add1(a[i], b[i], s[i], carray[i-1], carray[i]); } } void getTwoComplement(bool arr[32]){ for(int i=0;i<32;i++){ arr[i] = ! arr[i]; } bool temp[32]; bool one[32]; one[0] = true; for(int i=1;i<32;i++){ one[i] = false; } add32(arr, one, temp); for(int i=0;i<32;i++){ arr[i] = temp[i]; } } int add(int a, int b){ bool A[32], B[32], S[32]; getComplementCode(A, a); getComplementCode(B, b); add32(A, B, S); return getTrueValue(S); } int sub(int a, int b){ bool A[32], B[32], S[32]; getComplementCode(A, a); getComplementCode(B, b); getTwoComplement(B); add32(A, B, S); return getTrueValue(S); } int main() { cout << add(10, 5) << endl; return 0; } ``` 乘法的话,32 位加 32 位结果是 64 位的,按照这个方式也能够实现 我写的了一个测试用例如下 ``` BOOST_AUTO_TEST_CASE(addTest1){ const int times = 10000; int a = (int)random(); int b = (int)random(); BOOST_TEST(a + b == add(a, b)); } ``` 测试通过 除法和浮点数运算,计组课上没讲,不知道具体怎么做,不过道理都是相同的,模拟机器运算,把 C++写成 verilog |
6
vituralfuture 2023-06-11 19:45:34 +08:00
@vituralfuture 测试写错了,修改如下
``` BOOST_AUTO_TEST_CASE(addTest1) { const int times = 10000; int a, b; for (int i = 0; i < times; i++) { a = (int) random(); b = (int) random(); BOOST_TEST(a + b == add(a, b)); } } ``` 结果 |
7
yankebupt 2023-06-11 19:51:58 +08:00
你就直接问 GPT ,如何使用 AND OR XOR NOT 四个操作符实现加减乘除不就完了……
是人干的事么…… 话说经常有直播网站加载 wasm ,为了实现高于目标机器位数的乘除法(估计用于签名或加解密),可以略微参考一下,也不能算是完全没有用处。 |
8
javak 2023-06-11 20:25:28 +08:00
这个太简单了,十多年前,我大二的时候,《数据结构与算法设计》这门课,其中一节课的作业而已。
|
9
test0x01 2023-06-11 20:41:53 +08:00 via Android
利用 AST,很多语言提供现成的解析器,自己再后继处理下。这样算不算?
|
10
agagega 2023-06-11 20:43:46 +08:00 via iPhone
你的语言表述很不清晰。究竟是「不用这门语言的四则运算符实现四则运算」还是「用这门语言实现一个四则运算表达式的计算工具」?
|
12
duke807 2023-06-11 21:30:40 +08:00 via Android
没意义,即便你写一个 cpu 仿真代码,仿真 cpu 寄存器,依然会用到 “编程语言提供的基础四则运算”
建议 op 直接学 verilog ,可以帮助理解最最底层的东西 |
13
jorneyr 2023-06-11 22:31:09 +08:00
数据结构与算法的基础:逆波兰表达式。
|
14
lopssh 2023-06-11 22:36:42 +08:00 via Android
很基础啊...逆波兰式+表达式栈求值。
|
15
phcbest 2023-06-11 22:48:32 +08:00
```kotlin
fun add(a: Int, b: Int): Int { var carry: Int var sum: Int do { sum = a xor b carry = (a and b) shl 1 a = sum b = carry } while (b != 0) return a } fun subtract(a: Int, b: Int): Int { return add(a, add(b.inv(), 1)) } fun multiply(a: Int, b: Int): Int { var result = 0 var shift = 0 var bCopy = b while (bCopy != 0) { if (bCopy and 1 == 1) { result = add(result, a shl shift) } shift++ bCopy = bCopy shr 1 } return result } fun divide(a: Int, b: Int): Int { var dividend = a var divisor = b var quotient = 0 while (dividend >= divisor) { dividend = subtract(dividend, divisor) quotient = add(quotient, 1) } return quotient } ``` |
16
zktsin 2023-06-11 23:45:23 +08:00 via iPhone 1
阿隆佐·邱奇提出的 lambda 演算是一种形式系统,在它中,所有的函数都只有一个输入。你可以使用它来表示所有可计算的函数。为了用它实现加减乘除四则运算,我们先需要定义一些基础函数。
以下是用 JavaScript ES6 表示的四则运算的 lambda 演算: ```javascript const ZERO = f => x => x; const ONE = f => x => f(x); const TWO = f => x => f(f(x)); const THREE = f => x => f(f(f(x))); const SUCC = n => f => x => f(n(f)(x)); const PLUS = m => n => f => x => m(f)(n(f)(x)); const MULT = m => n => f => m(n(f)); const PRED = n => f => x => n(g => h => h(g(f)))(u => x)(u => u); const SUB = m => n => n(PRED)(m); const toInteger = n => n(x => x + 1)(0); let four = SUCC(THREE); console.log(toInteger(four)); // 4 let three = PRED(four); console.log(toInteger(three)); // 3 let seven = PLUS(three)(four); console.log(toInteger(seven)); // 7 let twelve = MULT(two)(six); console.log(toInteger(twelve)); // 12 let two = SUB(four)(two); console.log(toInteger(two)); // 2 ``` 这段代码首先定义了一些常数,如 `ZERO`、`ONE`、`TWO`、`THREE`。然后,定义了四则运算的函数 `SUCC`、`PLUS`、`MULT`、`PRED` 和 `SUB`。 其中 `SUCC` 是后继函数,表示加一操作。`PLUS` 是加法函数,它将两个数相加。`MULT` 是乘法函数,它将两个数相乘。`PRED` 是前驱函数,表示减一操作。`SUB` 是减法函数,它将两个数相减。 注意,所有的这些函数都是通过函数组合和应用来定义的,没有使用任何 JavaScript 特有的语法,完全按照邱奇的理论来实现。 然后,`toInteger` 函数用于将这些邱奇数转换为 JavaScript 中的整数,便于我们查看和验证结果。 最后的部分是一些运算示例,验证了这些函数的正确性。 注意,以上代码中的所有数都是邱奇数,它们都是以单参数函数的形式表示的。例如,`THREE` 是一个函数,它接受一个函数 `f` 和一个参数 `x`,并返回 `f(f(f(x)))`。这是邱奇数的标准表示方式。 |
17
crz 2023-06-12 10:27:45 +08:00
|
18
LykorisR 2023-06-12 10:51:34 +08:00
大一上计算机系统基础实验课程,和这个一模一样
|