Thread: Multiplication problem

  1. #1
    Registered User
    Join Date
    Feb 2008
    Posts
    147

    Multiplication problem

    My code works as follow:

    Code:
    #define h 12
    
    int x = 0;
    unsigned int y = 7
    
    x += ( 5 - y) * h
    I get x = -24 which it's ok

    but if I replace the define statement for this:

    Code:
    #define h 12.5f
    I dont get the expected result. I get -3276800. I would expect -25 whitch is a singed int result too.

    any idea?

  2. #2
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Is that the EXACT code you are using, or some sort of "a bit like this but not precisely"?

    It sounds like you are printing a float as a integer.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  3. #3
    Registered User
    Join Date
    Dec 2007
    Posts
    214
    You are trying to assign a floating point number to an integer. It won't work.

  4. #4
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by DaveH View Post
    You are trying to assign a floating point number to an integer. It won't work.
    Of course it does. You may get a warning for converting float to int, but it "works" in the respect that it does roughly what you expect.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  5. #5
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,412
    C99 section 6.3.1.3 states:
    When a value with integer type is converted to another integer type other than _Bool, if the value can be represented by the new type, it is unchanged.

    Otherwise, if the new type is unsigned, the value is converted by repeatedly adding or subtracting one more than the maximum value that can be represented in the new type until the value is in the range of the new type.

    (The rules describe arithmetic on the mathematical value, not the value of a given type of expression.)
    Consequently, (5 - y) does not give you -2, but some unsigned integer that could be rather large. Now, when you multiply this by 12, there is an overflow, and then when you convert the result to signed int, the value happens to be what you expected.

    The introduction of a float literal messed this accident up, and you got what you deserved, even though you did not expect it.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  6. #6
    Registered User
    Join Date
    Feb 2008
    Posts
    147
    I have just create a sample program with codeblocks and mingw:

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    #define     h1  12
    #define     h2  12.5f
    
    int main()
    {
        int x = 0;
        unsigned int y = 7;
    
        x += ( 5 - y) * h1;
        printf( "x = %d\n",x);
    
        x = 0; // Reset
        x += ( 5 - y) * h2;
        printf( "x = %d\n",x);
    
        return 0;
    }
    This is the output:
    Code:
    x = -24
    x = -2147483648
    I would expect a the int part of the float casted to int in the line "x += (5 - y) * h2" , but not. As you see, and if you compile the above, I dont get -25

  7. #7
    Registered User
    Join Date
    Feb 2008
    Posts
    147
    Quote Originally Posted by laserlight View Post
    C99 section 6.3.1.3 states:


    Consequently, (5 - y) does not give you -2, but some unsigned integer that could be rather large. Now, when you multiply this by 12, there is an overflow, and then when you convert the result to signed int, the value happens to be what you expected.

    The introduction of a float literal messed this accident up, and you got what you deserved, even though you did not expect it.
    OK!!!, thanks, difficult to understand, I solved by casting the unsigned as follow:

    x += ( 5 - (int) y) * h2;

  8. #8
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,412
    I suggest you try this:
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    #define     h1  12
    #define     h2  12.5f
    
    int main()
    {
        int x = 0;
        unsigned int y = 7;
    
        x += ( 5 - y) * h1;
        printf( "&#37;u\n", ( 5 - y) * h1);
        printf( "x = %d\n",x);
    
        x = 0; /* Reset */
        x += ( 5 - y) * h2;
        printf( "%f\n", ( 5 - y) * h2);
        printf( "x = %d\n",x);
    
        return 0;
    }
    What I have modified is to show you the value that will be added to x in each case. Check the value of INT_MAX. You probably will find that INT_MAX is smaller than the values to be added to x. Consequently:
    Quote Originally Posted by C99 on conversion of an integer to signed integer
    Otherwise, the new type is signed and the value cannot be represented in it; either the result is implementation-defined or an implementation-defined signal is raised.
    Quote Originally Posted by C99 on conversion of a floating point number to integer
    If the value of the integral part cannot be represented by the integer type, the behavior is undefined.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  9. #9
    Registered User
    Join Date
    Feb 2008
    Posts
    147
    Quote Originally Posted by Kempelen View Post
    OK!!!, thanks, difficult to understand, I solved by casting the unsigned as follow:

    x += ( 5 - (int) y) * h2;
    Ohhh!!!, there is something I am not understanding or doing bad..... I modify the sample little program with that and it works, but I put that (int) cast in my original program and dont work

    is that cast the solution or how did you modify the program to print the exact int?

  10. #10
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    The thing is that you're mixing integers and floats. This can pretty easily lead to unexpected results.
    Try to keep the entire line as a single type and you'll be less susceptible to undefined behaviour.
    If you have different types, try explicitly casting them to a correct type to keep the chain intact. The above modified code will yield the same result.
    See code example below.
    Last edited by Elysia; 05-21-2008 at 10:30 AM.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  11. #11
    Technical Lead QuantumPete's Avatar
    Join Date
    Aug 2007
    Location
    London, UK
    Posts
    894
    As someone once said to me: "The cardinal rule in using floating point numbers is: don't!" Not mixing signed and unsigned is just as important as not mixing floats and ints. That is unless you know that's the right thing to do and you explicitly tell the compiler so by casting.

    QuantumPete
    "No-one else has reported this problem, you're either crazy or a liar" - Dogbert Technical Support
    "Have you tried turning it off and on again?" - The IT Crowd

  12. #12
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Another example that yields correct result using the floating point:
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    #define     h1  12
    #define     h2  12.5f
    
    int main()
    {
    	int x = 0;
    	unsigned int y = 7;
    	float z;
    
    	x += ( 5 - y) * h1;
    	printf( "x = &#37;d\n",x);
    
    	x = 0; // Reset
    	x += ( 5 - y) * (int)h2;
    	printf( "x = %d\n",x);
    
    	z = 0; // Reset
    	z += ((float)5 - (float)y) * h2;
    	printf( "z = %f\n", z);
    
    	return 0;
    }
    This code yields correct results (-24, -24, -25).
    Last edited by Elysia; 05-21-2008 at 10:35 AM.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  13. #13
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,412
    This code yields correct results (-24, -24, -25).
    It should yield a compile error since this is C

    I think Kempelen's ( 5 - (int) y) * h2 works, and Kempelen has stated as much. What does not work is the original program when this change is incorporated, but we cannot help debug something that we have no knowledge of.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  14. #14
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Hmm, I wasn't aware C doesn't like type(x) casts instead of (type)x casts...
    I always compile as C++/C, but I just tried the above code and it compiles in C (at least with VS).
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  15. #15
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,412
    Hmm, I wasn't aware C doesn't like type(x) casts instead of (type)x casts...
    I always compile as C++/C, but I just tried the above code and it compiles in C (at least with VS).
    Must be a compiler extension. C99 does not provide for that syntax for casts.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Memory problem with Borland C 3.1
    By AZ1699 in forum C Programming
    Replies: 16
    Last Post: 11-16-2007, 11:22 AM
  2. Someone having same problem with Code Block?
    By ofayto in forum C++ Programming
    Replies: 1
    Last Post: 07-12-2007, 08:38 AM
  3. A question related to strcmp
    By meili100 in forum C++ Programming
    Replies: 6
    Last Post: 07-07-2007, 02:51 PM
  4. WS_POPUP, continuation of old problem
    By blurrymadness in forum Windows Programming
    Replies: 1
    Last Post: 04-20-2007, 06:54 PM
  5. ...multiplication using stacks
    By iiwhitexb0iii in forum C Programming
    Replies: 1
    Last Post: 10-09-2006, 01:28 AM

Tags for this Thread