将float转换为short以最小的精度损失

时间:2014-08-08 10:23:09

标签: java floating-point short

我有这个正弦波产生浮点值(例如0.37885),但我希望它们作为短路。使用short进行直接投射可以得到0值。那么解决方案是什么?

任何人都可以告诉我该怎么做 - 理想情况下不会损失精确度 - 或者如果可能的话,最小的精度损失很小?

4 个答案:

答案 0 :(得分:6)

public static short floatToShort(float x) {
    if (x < Short.MIN_VALUE) {
        return Short.MIN_VALUE;
    }
    if (x > Short.MAX_VALUE) {
        return Short.MAX_VALUE;
    }
    return (short) Math.round(x);
}

你将失去分数部分:

float    4 byte floating-point
double   8 byte floating-point (normal)
short    2 byte integer
int      4 byte integer (normal)
long     8 byte integer

<强> 编辑:

也许您想知道如何将 float (4个字节)的位保存到 int (4个字节): (http://docs.oracle.com/javase/7/docs/api/java/lang/Float.html#floatToRawIntBits(float)

float x = 0.1f;
int n = Float.floatToRawIntBits(x);
float y = Float.intBitsToFloat(n);

答案 1 :(得分:6)

原则上,您可以将它乘以100000,将其转换为int,然后减去-32,767并将其转换为short。如果仍然将所有值放在-32,767到32,767范围内,那么这可能是你能做到的最好的。否则,您必须限制精度并乘以10000.

当你使用短路时,你必须记得把它分开。

答案 2 :(得分:1)

shortintegral type,因此它只能包含整数。 0.37885 short0的唯一两个选项是1int,两者(在我看来)都会失去相当多的精确度。

所以答案是:如果你没有丢失所有小数值,可以使用强制转换,Float#shortValueMath.round(float)(并将生成的short转换为{ {1}})。

示例:Live Copy

float f1 = 0.37885f;
short s1 = (short)Math.round(f1);
System.out.println("s1 = " + s1);

float f2 = 27.67885f;
short s2 = (short)Math.round(f2);
System.out.println("s2 = " + s2);

输出:

s1 = 0
s2 = 28

在评论中你说:

  

我有这个正弦波产生如上所述的值,但我希望它们是短裤。

啊,现在,我们可以做点什么了。据推测,您获得的价值都在01之间。你可以通过乘法将它们存储为短裤。由于short的范围是-32,768到37,767,因此将它们乘以的方便数字可能是10000:

short s = Math.round(floatValue * 10000);

我们为您的示例获得的数字为3789。示例:Live Copy

float floatValue = 0.37885f;
short s = (short)Math.round((double)floatValue * 10000);
System.out.println("s = " + s);

那不是相同的值,当然,它的值乘以一万,所以无论你在哪里使用它,你都会#39 ; d必须允许。

答案 3 :(得分:0)

如果您的输入float值处于定义的范围内(现在让我们假设它们位于-1..1,独占的范围内),您可以将它们相乘以获得一个你将丢弃的分数。

有效的短距离为:-32768..32767因此在这种情况下您可以使用32768多个(最大短/最大输入值)。

例如:

float f = 0.23451f;
short s = (short) (f * 32768);

short值解码为float

float f2 = s / 32768f;