C 流十六进制数作为十进制数

C 流十六进制数作为十进制数,c,pi,C,Pi,我想使用BBP公式计算一个C程序的pthread进程中的Pi,而另一个进程则尽可能地打印结果。然而,BBP给出了一个基数为16的答案,而我想将基数为10的答案流式传输给用户 如何确定打印以10为基数转换的以16为基数的数字的第n位是否安全 提前谢谢 一种解决方案是测试增加当前可用的最后一个十六进制数字是否会更改您考虑显示的十进制数字 考虑一个十六进制表示的数字x…h3h2h1h0.h-1h-2…和十进制表示的数字…d3d2d1d0.d-1d-2 假设我们有一个截断的数字,所以我们只知道h中的数字

我想使用BBP公式计算一个C程序的pthread进程中的Pi,而另一个进程则尽可能地打印结果。然而,BBP给出了一个基数为16的答案,而我想将基数为10的答案流式传输给用户

如何确定打印以10为基数转换的以16为基数的数字的第n位是否安全


提前谢谢

一种解决方案是测试增加当前可用的最后一个十六进制数字是否会更改您考虑显示的十进制数字

考虑一个十六进制表示的数字x…h3h2h1h0.h-1h-2…和十进制表示的数字…d3d2d1d0.d-1d-2

假设我们有一个截断的数字,所以我们只知道h中的数字∞ 给hj。设y为这些数字表示的数字。设z为y+16j,在j位位置为y+1。 那么x的值可能是从y(包含)到z(独占)的任意值

现在考虑一个带有数字D的候选十进制数字∞ 去迪。设y'为这些数字表示的数字。设z'为y+10i。如果是≤ y和z≤ z',然后是十进制数字d∞ to di必须是x的完整十进制数字的前缀(即,已知这些十进制数字出现在x的十进制数字中;它们不会随着更多十六进制数字的发现而改变)


这是因为x的值[y,z],可以通过向y'添加一些零值或正值来形成,并且所需的值在i位位置小于1。相反,如果不等式不成立,则x可能超出候选数字所跨越的区间。

@Eric Postdischil发布了一个很好的通用算法

在实施OP目标时,可能会实现一些捷径。
单独处理Pi的整数部分,只处理分数。
假设输入为基数16,然后一次添加1位

实施说明:
我通过使用固定内存分配和字节数组(字符串)处理来作弊。当然,人们会保存数组长度,而不是
strlen()
,并使用字节0-9,而不是字符“0”到“9”,但这很快就被抛到了一起,这样更容易调试。数组大小是动态的,但很容易添加

#include <assert.h>
#include <memory.h>
#include <stdio.h>
#include <stdlib.h>

typedef struct {
  char *Sum;
  char *Add;
} Pi_T;

void Pi_Print(const char *Title, Pi_T *State) {
  printf("%s\n", Title);
  printf("  Sum: '%s'\n", State->Sum);
  printf("  Add: '%s'\n", State->Add);
}

// Sum += Add
void Pi_Add(char *Sum, char *Add) {
  size_t LenS = strlen(Sum);
  size_t LenA = strlen(Add);
  while (LenS > LenA) {
    Add[LenA++] = '0';
    Add[LenA] = '\0';
  }
  while (LenA > LenS) {
    Sum[LenS++] = '0';
    Sum[LenS] = '\0';
  }
  unsigned Accumulator = 0;
  while (LenA > 0) {
    LenA--;
    Accumulator += Add[LenA] - '0';
    Accumulator += Sum[LenA] - '0';
    Sum[LenA] = Accumulator % 10 + '0';
    Accumulator /= 10;
    assert(Accumulator <= 9);
  }
  assert(Accumulator == 0);
}

// Divide the `Add` by 2
void Pi_Div2(char *Add) {
  size_t LenS = strlen(Add);
  size_t i;
  unsigned Accumulator = 0;
  for (i = 0; i < LenS; i++) {
    Accumulator += Add[i] - '0';
    Add[i] = Accumulator / 2 + '0';
    Accumulator %= 2;
    Accumulator *= 10;
    assert ((Accumulator == 0) ||  (Accumulator == 10));
  }
  if (Accumulator > 0) {
    Add[i++] = Accumulator / 2 + '0';
    Add[i] = '\0';
    Accumulator %= 2;
    Accumulator *= 10;
    assert(Accumulator == 0);
  }
}

void Pi_PutHex(Pi_T *State, unsigned HexDigit) {
  // Add HexDigit, 1 bit at a time.
  for (unsigned i = 4; i-- > 0;) {
    if (HexDigit & (1 << i)) {
      Pi_Add(State->Sum, State->Add);
    }
    // Should the Sum[0] be extracted?
    if (State->Add[0] == '0') {
      for (size_t i = 1; State->Sum[i] && State->Add[i]; i++) {
        unsigned Accumulator = State->Sum[i] - '0' + State->Add[i] - '0';
        if (Accumulator > 9)
          break;
        if (Accumulator < 9) {

          // !!!!!!!!!!!!!!!!!!!!!!!!!!!!
          // Print the decimal digit!
          printf("%c", State->Sum[0]);
          // !!!!!!!!!!!!!!!!!!!!!!!!!!!!

          memmove(&State->Sum[0], &State->Sum[1], strlen(State->Sum));
          memmove(&State->Add[0], &State->Add[1], strlen(State->Add));
          break;
        }
      }
    }
    Pi_Div2(State->Add);
  }
}

void Pi_Test(void) {
  Pi_T State;
  State.Sum = malloc(500);
  State.Add = malloc(500);
  State.Sum[0] = '\0';
  State.Add[0] = '5';
  State.Add[1] = '\0';
  // http://calccrypto.wikidot.com/math:pi-hex
  static const char *pi = "3.243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89452821E638D01378";
  // http://www.miniwebtool.com/first-n-digits-of-pi/?number=100
  // 3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679
  // Output
  // 3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117
  const char *p = &pi[2];
  // Pi_Print("Init", &State);
  printf("3.");
  // add each hex digit, one at a time.
  while (*p) {
    unsigned HexDigit = (*p <= '9')  ? (*p - '0') : (*p - 'A' + 10);

    // !!!!!!!!!!!!!!!!!!!!!!!!!!!!
    // Put in the hexadecimal digit
    Pi_PutHex(&State, HexDigit);
    // !!!!!!!!!!!!!!!!!!!!!!!!!!!!

    p++;
  }
  printf("\n");
  // Pi_Print("End", &State);
}
#包括
#包括
#包括
#包括
类型定义结构{
字符*和;
字符*添加;
}皮尤;
无效Pi_打印(常量字符*标题,Pi_T*状态){
printf(“%s\n”,标题);
printf(“总和:'%s'\n',状态->总和);
printf(“添加:“%s”\n”,状态->添加);
}
//总和+=相加
void Pi_Add(char*Sum,char*Add){
镜头尺寸=斯特伦(总和);
尺寸=标准长度(增加);
while(镜头>镜头){
添加[LenA++]=“0”;
添加[LenA]='\0';
}
while(LenA>镜头){
和[镜头++]=“0”;
和[镜头]='\0';
}
无符号累加器=0;
而(LenA>0){
莉娜——;
累加器+=添加[LenA]-“0”;
累加器+=总和[LenA]-“0”;
总和[LenA]=累加器%10+'0';
累加器/=10;
断言(累加器0){
添加[i++]=累加器/2+'0';
添加[i]='\0';
累加器%=2;
累加器*=10;
断言(累加器==0);
}
}
void Pi_PutHex(Pi_T*状态,无符号十六进制数字){
//添加十六进制数字,每次1位。
对于(无符号i=4;i-->0;){
if(十六进制数字和(1和,状态->添加);
}
//是否应提取总和[0]?
如果(状态->添加[0]=“0”){
对于(大小i=1;状态->求和[i]&状态->添加[i];i++){
无符号累加器=状态->求和[i]-“0”+状态->添加[i]-“0”;
如果(累加器>9)
打破
if(蓄能器<9){
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!
//打印十进制数字!
printf(“%c”,State->Sum[0]);
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!
memmove(&State->Sum[0],&State->Sum[1],strlen(State->Sum));
memmove(&State->Add[0],&State->Add[1],strlen(State->Add));
打破
}
}
}
Pi_Div2(状态->添加);
}
}
无效Pi_测试(无效){
皮尤状态;
State.Sum=malloc(500);
State.Add=malloc(500);
State.Sum[0]='\0';
State.Add[0]=“5”;
State.Add[1]=“0”;
// http://calccrypto.wikidot.com/math:pi-六角形
静态常数char*pi=“3.243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89452821E638D01378”;
// http://www.miniwebtool.com/first-n-digits-of-pi/?number=100
// 3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679
//输出
// 3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117
常量char*p=&pi[2];
//Pi_打印(“初始”和状态);
printf(“3”);
//每次添加一个十六进制数字。
而(*p){

unsigned HexDigit=(*p“safe”在哪种意义上?不确定这是否可能。在程序的任何时候,如果您决定打印出数字,并且下一个值是a-f,那么前面的数字都可以更改,或者至少在我看来是这样的。@alk:让h[i]是数字的第i个十六进制数字,用h[0]编号作为最小整数位,h[-1]是1/16位,依此类推,让d[i]是同一数字的第i个十进制数字。我们要计算d[i],这意味着我们必须充分了解数字的值,对该值的进一步细化不会导致d[i]发生变化。因为j知道h的所有十六进制数字[无穷远]到h [j]足够了吗?谢谢你的回答。我可以等待打印,直到有更多的数字。从十六进制数字的输入流小数数字类似于调用C++ <代码> STD::矢量< /代码>。如果你真的想“流”。一个接一个地,每增加一个数字都会与已经输入的数字成线性关系。(类似于每次调用
push_back()
)后调整向量大小。谢谢你的回答。这对我来说很清楚。我将尝试实现这一点,并将查看chux对gu的回答