【问题标题】:Arithmetic with base 256 number system以 256 为基数系统的算术运算
【发布时间】:2017-07-20 15:13:16
【问题描述】:

我现在正在做一个项目,我需要对以 256 为底的数字进行计算。我正在读取文件的字节并将其存储在 uint8_t 的数组中(又名 unsigned charBYTE) .支持的最大数字数据类型不能满足我项目的需要。因此,字节数组的作用类似于自定义长度/大小数据类型 (BigInt)。

我现在需要对其进行算术运算,例如:-1, /2, %2

例如,这是演示我的数字应该如何工作的加法的样子:

9   + 1 = (10)
99  + 1 = (100)
255 + 1 = (1)+(0)<<8
255 + 2 = (1)+(1)<<8

注意:第一个是 10,因为 10 占 1 位,而第三个是 1 0,因为它占 2 位。我也无法将它们转换为整数,因为我必须处理 huge 数字。

我绞尽脑汁想办法在 C 中实现这一点,但无济于事。

到目前为止我的代码:

#include<stdio.h>
#include<string.h>
#include<stdint.h>
#include<stdlib.h>

typedef uint8_t BYTE;
BYTE buffer[1000000000];

void n(){
    printf("\n");
}

int main()
{
    uint32_t  x;
    x = 0; 
    int _len,y;
    char * test    = "test.bin";
    FILE * inptr = fopen(test,"rb");
    uint32_t i=0;
    while(fread(&buffer[i],1,1,inptr));
}

【问题讨论】:

  • 我不明白,你的问题是什么。您可以确定我们了解非 10 个碱基的算术是如何工作的。您没有显示任何代码。问你什么时候准备好。
  • 参见 Cant make value propagate through carry ,而不是 DWORD 更改为 BYTE 并相应地更新位掩码和移位
  • 将您的数组视为多项式(x == 256)。然后,您可以应用与多项式算术相同的算法。仅:您需要考虑溢出!
  • @DavideSpataro @EugeneSh。考虑(9)+(1) = (10)(255) + (2) = (1)(1),所以你的 256 位数字是放在括号中的值 0-255...
  • 我猜是因为没有在问题中展示您的任何工作并且没有明确说明问题所在。

标签: c algorithm math biginteger


【解决方案1】:

因此,您拥有 2 种操作的能力,可以轻松地将其转换为位操作......对于这种琐碎的事情不需要 bigint 库。假设你有号码

const int n=1000000000; // number size in bytes
BYTE x[n]; // number bytes let num[0] be LSW (least signifficant Word)

所以涉及的操作是:

  1. 模组:y = x%2 = x&amp;1

    这是O(1)

    BYTE y = x[0]&1;
    

    结果是一位,所以不需要将它存储为 bigint

  2. div:y = x/2 = x&gt;&gt;1

    这是O(n),结果也是 bigint 所以

    int i;
    BYTE y[n]; // result
    BYTE cy; // carry flag
    for (cy=0,i=n-1;i>=0;i--) // process all words from MSW to LSW
     {
     y[i] = ((x[i]>>1)&0x7F) | cy; // bitshifted word + last carry
     cy = (x[i]<<7)&0x80; // carry is shifted out lsb of word shifted to msb position
     }
    
  3. dec:y=x-1

    这是O(n),结果也是 bigint 所以

    int i;
    BYTE y[n]; // result
    BYTE cy; // carry flag
    for (cy=1,i=0;(i<n)&&(cy);i++) // process all words from LSW to MSW
     {
     y[i] = (x[i]-cy)&0xFF; // y[i] = sbc x[i],0
     cy = (x[i]==0x00); // carry
     }
    

希望我没有犯一些愚蠢的语法错误或其他什么,因为我将其直接编码到这里...

O(n) 操作都可以就地完成,您只需要在 x[i] 更改和缓冲旧进位之前缓冲实际的 x[i] 值或计算进位

在您的情况下,我会使用 32 位 (DWORD) 或 64 位 (QWORD) 而不是 8 位 (BYTE),这将提高速度,因为大多数计算机上的 ALU3264还是有点

如果您有兴趣实现更多 bigint 内容,请参阅:

[Edit1] dec 先用于 MSW

int i;
BYTE y[n]; // result
BYTE cy; // carry flag
for (cy=1,i=n-1;(i>=0)&&(cy);i--) // process all words from LSW to MSW
 {
 y[i] = (x[i]-cy)&0xFF; // y[i] = sbc x[i],0
 cy = (x[i]==0x00); // carry
 }

就地:

int i;
BYTE cy; // carry flag
for (cy=1,i=n-1;(i>=0)&&(cy);i--) // process all words from LSW to MSW
 {
 x[i] = (x[i]-cy)&0xFF; // y[i] = sbc x[i],0
 if (x[i]==0xFF) cy=1; // carry
 }

【讨论】:

  • 嘿,我遇到了减法问题。首先对我来说 x[0] 是最重要的数字。所以我将 i=0 更改为 i= len-1 和 i=0。这仅适用于 2 位数字。你能帮忙吗?
  • for(i =len-1 ;i>=0;i--) { if (buffer[i]!=0) { buffer[i] = buffer[i]-1; if (i
  • @rjpj1998 嗨,我添加了y=x-1 的实现,MSW 第一编码为edit1
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-12-17
  • 1970-01-01
  • 2023-03-03
  • 2023-03-25
  • 2019-05-13
  • 2020-02-18
  • 2011-07-18
相关资源
最近更新 更多