开发者

2 values should be the same but aren't

开发者 https://www.devze.com 2023-02-25 16:46 出处:网络
I have the following code which takes a HEX code somebody entered and transforms it into HSB: NSString *cString = [[hexText.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCh

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 substringW开发者_StackOverflow中文版ithRange: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?


Could be a floating-point precision issue. Using a float or a double does not store an exact value as using an int or long 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:

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);
    }
}
0

精彩评论

暂无评论...
验证码 换一张
取 消