什么输入到sprintf将产生0结果?

时间:2017-07-13 17:02:11

标签: c printf uint64 xlc

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

Warning

输出产生“0.00P”。

以下是我对参数的了解。输入为sprintf(strAtLeast10long, "%lld%c%.02uP", input/peta, decimal, (long)((input%peta) / (peta/hundred))); ,其值为> =(10 ^ 12 - (10 ^ 7/2))。 unsigned long long

decimal = '.'

是的,我知道static const long long hundred = 100; static const long long peta = 1000000000000000ULL; 会更好"%lld",我会解决这个问题。

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

编译器是IBM z / OS C ++编译器。在你们全都翻白眼之前去“EBCDIC是魔鬼的手工!”它是一个符合Posix的C ++编译器和环境。

4 个答案:

答案 0 :(得分:1)

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

你得到0.01P unsigned 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的评论一致,后者同时出现了。

答案 1 :(得分:1)

该输出的第一个要求是:

char decimal = '.';

然后范围内的每个input值:

0 to (1000000000000000ULL/100 - 1)

或同等的

0 to 10^13-1

将字符串设置为:

0.00P

这是因为输入需要低于:

peta/hundred

1000000000000000ULL/100

由于OP知道输入&gt; =(10 ^ 12 - (10 ^ 7/2)),最终答案是:

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

<强>更新

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

有了新限制,无输入值可以产生结果0.00P

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

OP的新要求是输入&gt; = peta - 10000000ULL 所以唯一有趣的范围是:

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

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

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

答案 2 :(得分: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

答案 3 :(得分:0)

我通过不相关的路线在爆炸中找到了计数器中的值。它是FWIW 0xFFFFFFFFFFFFFA67或18446744073709550183.舍入代码将其包装为0x0000048c27394a67或4999999998567,它非常小(!),格式为0.00P。

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