1

我正在尝试调试与此特定代码无关的问题,并且正在寻找线索,线索是“该计数器可能具有什么值?” 以下代码行

sprintf(strAtLeast10long, "%lld%c%.02uP", 
   input/peta, decimal, (long)((input%peta) / (peta/hundred)));

正在为输出生成“0.00P”。

这是我对参数的了解。输入是unsigned long long一个值 >= (10^12 - (10^7 / 2)) 的值。decimal = '.'

static const long long hundred =            100;
static const long long peta =  1000000000000000ULL;

是的,我知道这"%lld"会更好"%llu",我会解决这个问题。

但与此同时,我正在寻找有关输入内容的线索。问题发生在客户身上,我们不知道如何重现它,因此添加调试代码或使用调试器不是一种选择。

编译器是 IBM z/OS C++ 编译器。在你们翻白眼之前,“EBCDIC 是魔鬼的杰作!” 它是符合 Posix 的 C++ 编译器和环境。

4

4 回答 4

1

该输出的第一个要求是:

char decimal = '.';

然后input范围内的每个值:

0 to (1000000000000000ULL/100 - 1)

或同等学历

0 to 10^13-1

将字符串设置为:

0.00P

这是因为输入需要低于:

peta/hundred

这是1000000000000000ULL/100

由于 OP 知道input >= (10^12 - (10^7 / 2)),因此最终答案是:

input in the range (10^12 - (10^7 / 2)) to 10^13-1 will produce 0.00P

更新

在下面的评论中,OP 更改了对输入的限制,以便input >= (10^15 - (10^7 / 2))(注意 10^15 而不是 10^12 与问题不同)。

有了这个新的限制,没有输入值可以产生结果 0.00P

为了获得第一个0(来自input/peta),显然input必须小于peta

OP 的新要求是input >= peta - 10000000ULL所以唯一有趣的范围是:

peta - 10000000ULL <= input <= peta - 1

该范围内的所有值都会产生结果 0.99P。

结论:在给定的(新)限制下,没有输入值可以产生上述结果

于 2017-07-13T19:00:31.413 回答
1

有时可以使用蛮力测试。

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

void foo(unsigned i, unsigned long long input) {
  char decimal = '.';
  static const long long hundred = 100;
  static const long long peta = 1000000000000000ULL;
  char strAtLeast10long[10 + 100];

  // compile time warnings
  sprintf(strAtLeast10long, "%lld%c%.02uP", input / peta, decimal,
      (long) ((input % peta) / (peta / hundred)));

  if (strcmp("0.00P", strAtLeast10long) == 0) {
    printf("%u %llu %s\n", i, input, strAtLeast10long);
    fflush(stdout);
  }
}

unsigned long long rand_ull(void) {
  unsigned long long r = 0;
  for (unsigned i = 0; i < sizeof r; i++) {
    r *= 256;
    r ^= (unsigned) rand();
  }
  return r;
}

int main(void) {
  for (unsigned i = 0; i < 10000000; i++) {
    foo(i, rand_ull());
  }
  return 0;
}

输出

486814 1708844199629 0.00P
984885 8152599175962 0.00P
6266031 209118104328 0.00P
7365558 3983123923889 0.00P
于 2017-07-13T22:06:12.340 回答
1

使用您以最直接的方式提供的所有信息产生所描述的输出0.00P
unsigned long long input=999995000000ULL;我理解这是您给定范围内的最低允许值)
和 for
unsigned long long input=9999999999999ULL;,我认为这是指定输出的最高值。
可以合理地假设介于两者之间的任何值也给出相同的输出。

你得到0.01Punsigned long long input = 10000000000000ULL;这是一个更高的。

这是我的播放代码,
请检查是否与您描述的内容有任何冲突
(我将格式说明符字符串改编为我的编译器,gcc 版本 4.9.2 (tdm-1),目标:mingw32)。

#include <stdio.h>

int main(void)
{
    char decimal='.';

    char strAtLeast10long[]="                                \0";
    static const long long hundred =            100;
    static const long long peta =  1000000000000000ULL; 

    //unsigned long long input=  9999999999999ULL;
    //unsigned long long input=   999995000000ULL;
    unsigned long long input  = 10000000000000ULL;

    sprintf(strAtLeast10long, "%I64u%c%.02luP", input/peta, decimal, (long)((input%peta) / (peta/hundred)));

    printf("%s\n", strAtLeast10long );

    return 0;
}

这个答案与同时出现的xing的评论一致。

于 2017-07-13T18:10:33.433 回答
0

我通过不相关的路线在有问题的爆炸中找到了计数器中的值。它是 FWIW 0xFFFFFFFFFFFFFA67 或 18446744073709550183。舍入代码将其环绕为 0x0000048c27394a67 或 49999999998567,它是如此之小(!)它的格式为 0.00P。

抱歉,我没有更好地描述问题。10 的巨大力量是保持笔直和正确打字的 PITA。

于 2017-07-13T23:19:17.733 回答