16

如何将“32 位有符号定点数(16.16)”转换为浮点数?

(fixed >> 16) + (fixed & 0xffff) / 65536.0好吗?-2.5 怎么样?-0.5?

或者是fixed / 65536.0正确的方法?

(PS:带符号的定点“-0.5”在内存中看起来如何?)

4

3 回答 3

27

我假设二进制补码 32 位整数和运算符在 C# 中工作。

如何进行转换?

fixed / 65536.0

是正确且易于理解的。


(fixed >> 16) + (fixed & 0xffff) / 65536.0

相当于上面的正整数,但速度较慢,更难阅读。您基本上是在使用分配定律将单个分区分成两个分区,并使用位移位编写第一个分区。

对于负整数fixed & 0xffff不会给你小数位,所以它对于负数是不正确的。

查看-1应该映射到的原始整数-1/65536。此代码65535/65536改为返回。


根据您的编译器,它可能会更快:

fixed * (1/65536.0)

但我认为大多数现代编译器已经进行了这种优化。

无论如何,带符号的定点“-0.5”在内存中看起来如何?

反转转换给我们:

RoundToInt(float*65536)

设置float=-0.5给了我们:-32768.

于 2011-12-26T20:14:16.033 回答
6
class FixedPointUtils {
  public static final int ONE = 0x10000;

  /**
   * Convert an array of floats to 16.16 fixed-point
   * @param arr The array
   * @return A newly allocated array of fixed-point values.
   */
  public static int[] toFixed(float[] arr) {
    int[] res = new int[arr.length];
    toFixed(arr, res);
    return res;
  }

  /**
   * Convert a float to  16.16 fixed-point representation
   * @param val The value to convert
   * @return The resulting fixed-point representation
   */
  public static int toFixed(float val) {
    return (int)(val * 65536F);
  }

  /**
   * Convert an array of floats to 16.16 fixed-point
   * @param arr The array of floats
   * @param storage The location to store the fixed-point values.
   */
  public static void toFixed(float[] arr, int[] storage)
  {
    for (int i=0;i<storage.length;i++) {
      storage[i] = toFixed(arr[i]);
    }
  }

  /**
   * Convert a 16.16 fixed-point value to floating point
   * @param val The fixed-point value
   * @return The equivalent floating-point value.
   */
  public static float toFloat(int val) {
    return ((float)val)/65536.0f;
  }

  /**
   * Convert an array of 16.16 fixed-point values to floating point
   * @param arr The array to convert
   * @return A newly allocated array of floats.
   */
  public static float[] toFloat(int[] arr) {
    float[] res = new float[arr.length];
    toFloat(arr, res);
    return res;
  }

  /**
   * Convert an array of 16.16 fixed-point values to floating point
   * @param arr The array to convert
   * @param storage Pre-allocated storage for the result.
   */
  public static void toFloat(int[] arr, float[] storage)
  {
    for (int i=0;i<storage.length;i++) {
      storage[i] = toFloat(arr[i]);
    }
  }

}
于 2012-07-09T09:26:51.687 回答
0

在阅读了CodesInChaos的回答后,我写了一个 C++ 函数模板,非常方便。您可以传递小数部分的长度(例如,BMP 文件格式使用 2.30 定点数)。如果省略小数部分长度,则函数假定小数部分和整数部分具有相同的长度

#include <math.h> // for NaN
#include <limits.h> // for CHAR_BIT = 8

template<class T> inline double fixed_point2double(const T& x, int frac_digits = (CHAR_BIT * sizeof(T)) / 2 )
{
  if (frac_digits >= CHAR_BIT * sizeof(T)) return NAN;
  return double(x) / double( T(1) << frac_digits) );
}

如果你想从内存中读取这样的数字,我写了一个函数模板

#include <math.h> // for NaN
#include <limits.h> // for CHAR_BIT = 8

template<class T> inline double read_little_endian_fixed_point(const unsigned char *x, int frac_digits = (CHAR_BIT * sizeof(T)) / 2)
// ! do not use for single byte types 'T'
{
  if (frac_digits >= CHAR_BIT * sizeof(T)) return NAN;

  T res = 0;

  for (int i = 0, shift = 0; i < sizeof(T); ++i, shift += CHAR_BIT)
    res |= ((T)x[i]) << shift;

  return double(res) / double( T(1) << frac_digits) );
}
于 2018-01-31T13:15:44.367 回答