2 个值应该相同但不是
我有以下代码,它接受某人输入的十六进制代码并将其转换为 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。有什么想法吗?我认为这与第二位代码返回不准确的十六进制代码有关,但不确定在这种情况下如何使其更准确?
I have the following code which takes a HEX code somebody entered and transforms it into 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;
}
I then have this code which does the opposite - transforms HSB into a hex code:
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)];
These should both give the same value, and most of the time it does. But sometimes I will type in a hex code such as 208DBC and it will return 1F8CBC. Any ideas? I think it's something to do with the second bit of code returning an inaccurate hex code, but not sure how to make this more accurate in this case?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
可能是浮点精度问题。使用
float
或double
并不像使用int
或long
那样存储精确的值。它存储 IEEE-754 规范 允许的精确值的最接近近似值。存储值和精确值之间的差异通常非常小,但它可能足够大,以至于当您转换回整数时,您的值会被截断为下一个较小的整数。这就是输出中发生的情况(即0x1F = 0x20 - 1
、0x8C = 0x8D - 1
)。下面的代码可以说明这个问题:
Could be a floating-point precision issue. Using a
float
or adouble
does not store an exact value as using anint
orlong
does. It stores the closest approximation of the exact value allowed by the IEEE-754 spec. The difference between the stored value and the exact value is generally very small, but it may be just big enough that when you convert back to an integer your value gets truncated to the next smaller integer. That is what is happening in your output (i.e.0x1F = 0x20 - 1
,0x8C = 0x8D - 1
).The following code may illustrate the issue: