【问题标题】:Infer smallest possible data type without accuracy loss在不损失精度的情况下推断最小可能的数据类型
【发布时间】:2019-01-01 07:58:14
【问题描述】:

我有一个输入,它是 String。输入将始终是十进制数的String 表示,例如以下示例之一:

  3.14159265
  314159265
  314159265e5

我定义了一个名为Typesenum,它有两个成员:Types.FLOATTypes.DOUBLE

我想编写一个函数,该函数将为所有可以表示为float不失去准确性的输入返回Types.FLOAT,并为所有其他可以表示为的输入返回Types.DOUBLE double 不失准确性。如果double 的数字太准确,则应返回null 之类的内容。

众所周知float 的大小为 32 位,而double 的大小为 64 位。 将double 转换为float 会导致准确性下降,例如:

 3.14159265 --> 3.141592
 314159265 --> 314159200
 314159265e5 --> 314159200e5

需要澄清的一些事情:

  • 我实际上并不想将我的输入解析为其中一种类型。 我只需要这些信息,以便将其传递给 Hive
  • 不使用最小准确度数据类型是不可接受的。

【问题讨论】:

  • 抱歉说得太清楚了,我的最后一个问题被不知道floatdouble 区别的人扼杀了。
  • 你能检查Float.parseFloat(str);,如果不能解析,检查Double.parseDouble(str);吗?
  • @notyou parseFloat 无论如何都会解析,但会失去很多准确性。
  • 我认为最好的方法是使用 FloatDouble 解析它,然后再次使用一些任意精度库并比较结果。自己处理浮点解析可能会变得丑陋。
  • 那么试试类似:stackoverflow.com/questions/26099818/…。仅供参考,它是,而不是输。

标签: java floating-point inferred-type


【解决方案1】:

浮点数有 2 个主要部分,有效数和指数。根据维基百科:https://en.wikipedia.org/wiki/IEEE_754 32 位可以表示 7.22 位和 -126:127 的指数。 double 可以在指数中执行 15.95 位和 -1022:1023 位。

所以我会做如下的事情(sudo 代码)

public static FloatingPointEnum getType(String number){

    // Looks for the digits ignoring possible leading / trailing zeros
    int numDigits = getDigits(number);

    // Counts the leading / trailing zeros
    int exponent = getExponent(number);

    if(numDigits < 7 && exponent > -126 && exponent < 127){
        return _32Bit; 
    } else if(numDigits < 15 && exponent > -1022 && exponent < 1023){
        return _64Bit;
    } else {
        return null;
    }
}

【讨论】:

  • 这看起来是一个不错的解决方案,但你确定指数和数字在大小上是分离的吗?
  • 注意:-126、127、-1022 和 1023 都是二进制指数,而 7 和 15 是十进制数字。可以导出十进制指数。
  • 我会尝试numDigits &lt;= 7。但是对于真正的最小表示,需要二进制数字。
  • 如果你有 0.0006789 你需要一个双倍的数字。它是 4 位精度,指数为 -128,需要适合双精度数。
  • 1.40129846432481707092372958328991613128026194187651577175706828388979108268586060148663818836212158203125×10 ^ -45是精确表示作为float,但是这个代码将返回_64Bit,即使其在指数范围的错误是固定的。并且有少于七个有效十进制数字的数字不能完全表示为float,但此代码将返回_32Bit
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-06
  • 1970-01-01
  • 2019-10-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多