我正在编写一个创建ICC颜色格式的程序。这些格式指定一个名为s15Fixed16Number的数据类型,它具有符号位,15个整数位和16个小数位。 IEEE 754 32位浮点数具有符号位,8个指数位和23个小数位。
我需要从文本框中获取输入,并将它们转换为s15Fixed16Number。有些搜索在Google图书上显示this,但这是在谈论将十进制数转换为s15Fixed16Number。我想我可以使用链接中解释的方法,但我还没有做任何测试来确定它的准确性。我想我也可以尝试从文本框转换字符输入,但我还没有想过那么多。
我正在使用Cocoa,但我不认为这很重要;任何C函数都应该有效。以下是s15Fixed16Number格式的一些示例值:
-32768.0 = 0x80000000
0 = 0x00000000
1.0 = 0x00010000
32767 + (65535/65536) = 0x7FFFFFFF
我想从数值计算类开始已经有一段时间了!
答案 0 :(得分:2)
不要忘记浮子的内部表示。定点值只是整数,具有恒定的比例因子。请记住,浮点数的精度比目标格式更有限,因此对于较大的值,预期值可能会在较低的9位中关闭。
//s15Fixed16Number is presumably typedef'ed to unsigned int
float foo = 1.0f;
int fooFixedSigned = (int)(foo * 65536);
s15Fixed16Number fooFixed = (s15Fixed16Number)(abs(fooFixedSigned));
if (foo < 0) fooFixed = fooFixed | (1 << 31);
//you'll also need to explicitly check for overflows and underflows and handle them however is appropriate to your situation
编辑:更正&amp;到|
答案 1 :(得分:2)
假设你的C环境有2个补码整数,那么这比看起来要简单得多。
typedef long s1516; // 32bit 2's complement signed integer
s1516 floattos1516(double f) {
return (s1516)(f * 65536. + 0.5);
}
表示是固定点值,具有16位分数。这与有理数相同,其分母始终为65536(或2 16 )。要从浮点值形成这样的理性,您只需乘以分母。然后它只是一个适当的舍入问题,并截断为整数类型。
标准选择了他们所做的表格,因为如果你的系统使用2的补码整数运算,这就行了。虽然最左边的位确实代表符号,但它不是浮点表示中使用的符号位。
如果您的计算是真正的float
而不是double
,您会发现计算中的精确度不如满量程附近的数字的固定点值。如果以double
计算,那么计算中的精度将始终高于结果。
修改强>
明显的最新规范from the ICC为规范ICC.1:2004-10(配置文件版本4.2.0.0)。第5.1.3节:
5.1.3 s15Fixed16Number
固定的带符号的4字节/ 32位数量 16个小数位,如表3所示。
Table 3 — s15Fixed16Number Number Encoding -32768,0 80000000h 0 00000000h 1,0 00010000h 32767 + (65535/65536) 7FFFFFFFh
除了小数点表示的局部偏好之外,这些值完全符合我的理解,即表示只是带符号2的补码整数,应除以65536以得到它们的值。
表示的自然转换只是乘以65536,并从中简单地除以。选择合适的舍入规则是一个优先考虑的问题。
满量程范围从-32768.0(0x80000000)到大约32767.9999847412(0x7fffffff),包括在内。
我同意,如果规范恰好以十六进制显示任何负值的表示,那将更清楚。我浏览了整个文档,我发现的十进制和十六进制表示的唯一值是CIE XYZ色度坐标,根据定义范围从0到1,因此无法作为示例负值。