我有以下代码,它输入有人输入的HEX代码并将其转换为HSB:
NSString *cString = [[hexText.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] uppercaseString];
// String should be 6 or 8 characters
if ([cString length] < 6) NSLog(@"UH OH");
// strip 0X if it appears
if ([cString hasPrefix:@"0X"]) cString = [cString substringFromIndex:2];
if ([cString length] != 6) NSLog(@"UH OH");
// Separate into r, g, b substrings
NSRange range;
range.location = 0;
range.length = 2;
NSString *rString = [cString substringWithRange:range];
range.location = 2;
NSString *gString = [cString substringWithRange:range];
range.location = 4;
NSString *bString = [cString substringWithRange:range];
// Scan values
unsigned int r, g, b;
[[NSScanner scannerWithString:rString] scanHexInt:&r];
[[NSScanner scannerWithString:gString] scanHexInt:&g];
[[NSScanner scannerWithString:bString] scanHexInt:&b];
float red = r / 255.0f;
float green = g / 255.0f;
float blue = b / 255.0f;
float colorArray[3];
colorArray[0] = red;
colorArray[1] = green;
colorArray[2] = blue;
int max;
int min;
min=0;
max=0;
for(int i=1; i<3; i++)
{
if(colorArray[i] > colorArray[max])
max=i;
if(colorArray[i] < colorArray[min])
min=i;
}
if(max==min)
{
h3=0;
s3=0;
b3=colorArray[0];
}
else
{
b3=colorArray[max];
s3=(colorArray[max]-colorArray[min])/(colorArray[max]);
if(max==0) // Red
h3 = (colorArray[1]-colorArray[2])/(colorArray[max]-colorArray[min])*60/360;
else if(max==1) // Green
h3 = (2.0 + (colorArray[2]-colorArray[0])/(colorArray[max]-colorArray[min]))*60/360;
else // Blue
h3 = (4.0 + (colorArray[0]-colorArray[1])/(colorArray[max]-colorArray[min]))*60/360;
}
然后我有这个相反的代码 - 将HSB转换为十六进制代码:
UIColor *forC = colourPreview.backgroundColor;
const CGFloat *c = CGColorGetComponents([forC CGColor]);
CGFloat r, g, b;
r = c[0];
g = c[1];
b = c[2];
if (r < 0.0f) r = 0.0f;
if (g < 0.0f) g = 0.0f;
if (b < 0.0f) b = 0.0f;
if (r > 1.0f) r = 1.0f;
if (g > 1.0f) g = 1.0f;
if (b > 1.0f) b = 1.0f;
hexWithoutHash = [NSString stringWithFormat:@"%02X%02X%02X",
(int)(r * 255), (int)(g * 255), (int)(b * 255)];
这些都应该给出相同的值,并且大部分时间都是这样。但有时我会键入一个十六进制代码,如208DBC,它将返回1F8CBC。有任何想法吗?我认为这与第二位代码返回一个不准确的十六进制代码有关,但不确定如何在这种情况下使这更准确?
答案 0 :(得分:2)
可能是浮点精度问题。使用float
或double
并不会像使用int
或long
那样存储确切的值。它存储IEEE-754 spec所允许的精确值的最接近的近似值。存储值和精确值之间的差异通常非常小,但它可能足够大,当您转换回整数时,您的值会被截断为下一个较小的整数。这就是您的输出中发生的情况(即0x1F = 0x20 - 1
,0x8C = 0x8D - 1
)。
以下代码可说明问题:
for (int redColor = 0; redColor < 256; redColor++) {
int originalRed = redColor;
float red = originalRed / 255.0f;
float redMultiplied = red * 255;
int newRed = (int)redMultiplied;
if (newRed != originalRed) {
NSLog(@"Value mismatch detected: origianlRed=%d, red=%f, redMultiplied=%f, newRed=%d",
originalRed, red, redMultiplied, newRed);
}
}