【问题标题】:How to see the size of the incoming floating point number?如何查看传入浮点数的大小?
【发布时间】:2020-05-10 08:36:04
【问题描述】:

用户将一个数字写入输入,它存储在一个字符串中。如何检查此数字是否包含在 float 类型的大小中,还是需要 double

【问题讨论】:

  • 总是(是的,总是)使用double。如果没有充分的理由,甚至不要考虑floatlong double老师告诉我使用float只是在要求澄清/证明之后的一个强有力的理由。
  • 你在说什么数字? -7000000? 0.0000000000042? 3.14? 3.14159265358979323846? 7.3*10^365?
  • 你确实需要在编译时做出决定,这意味着检查传入的字符串不是一种选择。
  • 这似乎是一个 XY 问题。通常,您不会根据输入选择变量的类型。您选择一种可以处理您想要的输入的类型。
  • @pmg:哦,停下。是的,这个特定的问题对于为什么在floatdouble 之间进行选择有些神秘,但是强调始终使用double 的建议是不合适的。使用卷积、FFT 和类似算法处理 8 位传感器数据的人不需要double,它的内存占用会适得其反。大多数做神经网络处理的人不需要double

标签: c floating-point double scanf ieee-754


【解决方案1】:

除非您的浮点数很大或极小,即超出 -3.4E38 到 3.4E38 的范围,否则浮点数 32 将存储您在大小上而不是准确性方面投入的任何内容。因此,真正的问题是您需要多少有效数字才能最大限度地减少舍入误差。我推荐你阅读https://www.itu.dk/~sestoft/bachelor/IEEE754_article.pdf

如果您不受磁盘空间或内存的限制,那就选择 float 64。

【讨论】:

  • 即使在那个范围内,也有很多值不能用浮点数表示,所以从技术上讲,它不会存储“你扔给它的任何东西”。当然,双倍也不会,但它会更接近。
【解决方案2】:

如何检查此数字是否包含在 float 类型的大小中,还是需要 double

编码为字符串的数字提供了无限的可能性。有限 floatdoublerangeprecision 中受到限制。

请注意,floatdouble 的子集。

float 类型的值集合是double 类型的值集合的子集; C17dr § 6.2.5 10

范围

double 的范围通常远远超过float 的范围。

精度

典型的 floatdouble 是 2N * a dyadic rational:一些整数/一些二次方。因此,从 string 到浮点的转换涉及一些舍入。例如。 0.1 通常完全不能表示为floatdouble

这意味着大多数不精确的转换,即使在float 范围内,double 的答案也会比float 更接近。


为了达到 OP 的目标,我建议将字符串转换为两者并测试转换结果。

int float_or_double_range(const char *s) {
  char *endptr;
  errno = 0;
  double d = strtod(s, &endptr);
  if (s == endptr) return 'n';  // Neither
  if (errno == ERANGE) return 'd';

  errno = 0;
  double f = strtof(s, &endptr);
  if (s == endptr) return 'd';
  if (errno == ERANGE) return 'd';

  if (d == f) return 'f'; // encodable as float and double
  return 'd';
}

注意事项:

回想一下,FP strto...() 函数的正确性受实现质量问题的影响,并且它们本身可能无法在所有情况下都提供最佳答案。

要查找转换后的字符串值是否与doublefloat 相同,我建议不要将字符串 转换为double,然后将double 转换为float .这涉及double rounding 并在极端情况下引入错误。

【讨论】:

    【解决方案3】:

    此答案仅适用于正浮点数,但它可能会对您有所帮助:

    IEEE 754 定义的32 位浮点数(8 字节/单精度)具有3.40282 x 10^38 的最大正数float,最小正数float1.17549 x 10^-38

    使用strtod() 将字符串中的数字转换为double。这是必需的,因为您实际上不知道该号码是否已经是 double

    然后检查数字是否在上面提供的范围内。

    如果是,分配一个float。如果没有,请继续使用double 对象。

    这种方式有点混乱,因为你已经分配了一个double,然后选择要么使用之前用作缓冲区的double,要么分配另一个float。尽管如此,如果您根据字符串的数量分配例如一个数组,这将是有益的。此外,您还可以选择在使用后动态分配缓冲区double 对象和free()


    更简单的方法是从一开始就选择double。因此,请确保确实需要此过程。除非没有明确禁止使用double,否则请使用double

    这将为您节省大量时间和精力,也是最安全的方式。

    【讨论】:

    • 在 IEEE-754 binary32 中可表示的最大数是 ∞,而不是 3.40282e38。后者大约是可表示的最大有限数,2**1024−2**971。
    • binary32 的“最小正数”更像1.40129846e-45。 1.17549 x 10^-38 大约是最小的正常正值float
    猜你喜欢
    • 1970-01-01
    • 2020-08-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-15
    • 2018-07-09
    • 2017-03-31
    • 1970-01-01
    相关资源
    最近更新 更多