我正在尝试在Clojure中编写一个图像处理库,但在编写测试时我遇到了一个问题。
图像数据存储为整数的2D数组,这些整数是有符号的(Java,扩展名为Clojure,没有无符号整数)。我有一个函数来获取给定坐标对的像素。我对该函数的测试看起来像这样:
(is (= (get-pixel image 0 (dec width)) 0xFFFF0000))
即,查看(0,width-1)处的像素是否为红色。问题是,get-pixel返回一个signed int,但Clojure将0xFFFF0000视为long。在这种情况下,get像素返回-65536(十六进制为0xFFFF0000),Clojure正在检查它是否等于4294901760。
现在,我有几个选择。我可以使用十六进制的有符号整数解释作为小数(-65536)重写测试,但我认为这使得测试的意图不太清楚。我可以编写一个函数来将负数转换为正数,但这是一个复杂的附加层。最简单的方法可能就是在两个数字之间做一个按位,然后查看它是否有变化,但这看起来仍然比它应该更复杂。
是否有任何内置方法强制0xFFFF0000被评估为有符号整数而不是长整数,或者对两个任意数字进行逐位比较? int函数不起作用,因为该数字太大而无法表示为signed int。
谢谢!
答案 0 :(得分:4)
在clojure 1.3中,有一个unchecked-int
函数,它只占用最后四个字节并使它们成为一个int:
user> (unchecked-int 0xffff0000)
-65536
Clojure不允许您输入不同大小的字面数字,这有点令人伤心 - 这里我们做的是等同于Java (int)0xffff0000L
。
答案 1 :(得分:0)
你使用什么样的clojure版本?在1.3版本中,原始处理方式发生了很大变化。我做了一些实验,似乎得到的结果与你描述的不同。
user=> (int 0xFFFF0000)
IllegalArgumentException Value out of range for int: 4294901760 clojure.lang.RT.intCast (RT.java:1093)
user=> (long 0xFFFF0000)
4294901760
user=> *clojure-version*
{:major 1, :minor 3, :incremental 0, :qualifier nil}
如果您使用的是1.3,则可以使用long
功能。您还可以使用ByteBuffer操作数据并更直接地处理字节,尽管您将永远无法获得使用C的控制级别。