我有这个正弦波产生浮点值(例如0.37885),但我希望它们作为短路。使用short进行直接投射可以得到0值。那么解决方案是什么?
任何人都可以告诉我该怎么做 - 理想情况下不会损失精确度 - 或者如果可能的话,最小的精度损失很小?
答案 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)
short
是integral type,因此它只能包含整数。 0.37885
short
中0
的唯一两个选项是1
或int
,两者(在我看来)都会失去相当多的精确度。
所以答案是:如果你没有丢失所有小数值,可以使用强制转换,Float#shortValue
或Math.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
在评论中你说:
我有这个正弦波产生如上所述的值,但我希望它们是短裤。
啊,现在,我们可以做点什么了。据推测,您获得的价值都在0
和1
之间。你可以通过乘法将它们存储为短裤。由于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;