Dismiss Notice
Join Physics Forums Today!
The friendliest, high quality science and math community on the planet! Everyone who loves science is here!

What does c = t < 0 in C mean?

Tags:
  1. Jul 6, 2015 #1
    This is a very basic question, but one that's vexed me for a while. Are these two fragments equal:-


    In C, with c and t as integers
    c = t < 0

    and in Java, also with integers
    if (t < 0) {
    c = -1;
    } else {
    c = 0;
    }


    Reason I ask is that my Java interpretation works with any combination of t & c, and I can't tell which is the correct translation...
     
  2. jcsd
  3. Jul 6, 2015 #2

    phinds

    User Avatar
    Gold Member
    2016 Award

    I don't do JAVA but my understanding is that it is a strongly typed language and as such it should have inherent "true" and "false" variables and your c variable in JAVA should be typed as boolean, so I'd say your JAVA statements should use true and false, not -1 and 0. Does JAVA do auto-conversion from integer to Boolean?
     
  4. Jul 6, 2015 #3

    D H

    User Avatar
    Staff Emeritus
    Science Advisor

    No. Fortran has this right. C/C++, and languages based on it such as Java, have it wrong (in my opinion).

    In C, c = t < 0 sets c to zero or one. The problem with that is that zero and one differ by one bit. This is not a good idea in an environment that is prone to random bit flips.

    OTOH, Fortran seeks to make boolean expressions such as t < 0 evaluate to two values that are diametrically opposed, bitwise. Your Java code emulates how Fortran works. It uses -1(all bits set on a two's complement machine) rather than 1 (only the least significant bit set).
     
  5. Jul 6, 2015 #4

    wle

    User Avatar

    In C, this is read as c = (t < 0) and does the same thing as
    Code (C):
    if (t < 0) {
        c = 1;
    } else {
        c = 0;
    }
    Java has a separate boolean type and doesn't support casting booleans to integers or vice versa, so in Java c = t < 0 is equivalent to
    Code (Java):
    if (t < 0) {
        c = true;
    } else {
        c = false;
    }
    which the compiler will choke on if c is of type int.

    How to "translate" the C code into Java depends on why you're doing this and what you want to accomplish. If there's a specific reason you want to assign integers like 1 or 0 to c, then assign those integers. If you just want to save the result of a test, then make c a boolean:
    Code (Java):
    boolean c;

    c = t < 0;

    [Edit: Since C99, C also defines a boolean type (_Bool), but it's effectively an integer that can only be assigned values 0 and 1 and isn't integrated into the language the way boolean is in Java (e.g. the C language standard says that the value of the expression t < 0 is of type int rather than _Bool).]
     
    Last edited: Jul 7, 2015
  6. Jul 7, 2015 #5
    This is the entire code (sic). Should have posted it earlier. Now I'm starting to doubt that it's C at all. I assumed that it was C. It's from:-

    Good Practice in (Pseudo) Random Number Generation for Bioinformatics Applications
    David Jones, UCL Bioinformatics Group
    (Last revised May 7th 2010)


    Code ( (Unknown Language)):

    /* Implementation of a 32-bit KISS generator which uses no multiply instructions */
    static unsigned int x=123456789,y=234567891,z=345678912,w=456789123,c=0;
    unsigned int JKISS32()
    {
    int t;
    y ^= (y<<5); y ^= (y>>7); y ^= (y<<22);
    t = z+w+c; z = w; c = t < 0; w = t&2147483647;
    x += 1411392427;
    return x + y + w;
    }
     
    My problem lurks within the line beginning t = z... I think that c must be a number and not a boolean as it's used in an addition in this line. The code runs with my interpretation, but also with others and all produce reasonable output. This means I can't fix it. So help please!
     
  7. Jul 7, 2015 #6

    Vanadium 50

    User Avatar
    Staff Emeritus
    Science Advisor
    Education Advisor

    By precedence, one can rewrite it as c = (t > 0), and the equals sign expresses assignment. So that means c is?

    Also, in C, what is 1 + false?
     
  8. Jul 7, 2015 #7

    wle

    User Avatar

    That's C code, but (among other things) it's meant to be easy to translate to languages that don't have an unsigned integer type (like Java). It's written not to use multiplication because multiplication works differently for signed and unsigned integers.

    To get the equivalent result in Java:
    • Change y ^= (y>>7); to y ^= (y>>>7); (i.e., use Java's "unsigned right shift" operator).
    • Change c = t < 0; to c = (t < 0) ? 1 : 0;.

    It's probably a good idea to try out both the C and Java versions and check that they produce the same sequence.
     
    Last edited: Jul 7, 2015
  9. Jul 7, 2015 #8

    Thanks. And should all the variables be longs or shorts, because again it works well with both..? I suspect longs if they're to operate unsigned. But then it's meant to be 32 bit and not 64 bit. (I HATE SIGNED JAVA :mad: ESPECIALLY BYTES)
     
  10. Jul 7, 2015 #9

    wle

    User Avatar

    int, since the algorithm is meant for 32 bit integers. Some of the numbers will be interpreted as negative in Java, e.g. if you print them to the console or multiply them by other numbers, but the bit sequences in memory should be the same.

    If you really need the result to be a positive integer, you can always add 2L << 31 (i.e., ##2^{32}##) if the result is negative and save the result as a long at the end.
     
  11. Jul 8, 2015 #10
    Okay, I see some dangerous talk about types here.

    Remember
    char <= short <= int <= long <= long long

    You have absolutely no guarantee that an int is 32 bits, you don't even have a guarantee that these are different. If you want to assure yourself certain sizes:

    Code (Text):
    #include <cstdint>

    int8_t my8bit = 111;  //Always 8 bit
    int16_t my16bit = 1111; //Always 16 bit
    int32_t my32bit = 11111;  //Always 32 bit
     
  12. Jul 8, 2015 #11

    D H

    User Avatar
    Staff Emeritus
    Science Advisor

    It's definitely C code. In C, the comparison operators (<, >=, >, <=, ==, !=) evaluate to zero or one, not false or true.

    Why are you using this? In one thread, you want bits from pi as a source of pseudo random numbers. Now you are trying to use some variant of KISS. Why? I've asked you before, you haven't answered.


    The answer to "Is X a good source of pseudo random numbers" depends very much on the application. If your goal is to add a bit of apparent randomness to a video game, even rand() is probably OK. You need to toss rand() if your goal is to perform some Monte Carlo analyses that depend on a PRNG with good frequency behaviors. Mersenne Twister works great (and is very fast) for this kind of application. You need to toss Mersenne Twister if your goal is cryptographically secure encryption. You also need to toss bits from pi, KISS, and a boatload of other pseudo random generators. Generating a sequence of cryptographically secure random numbers is a hard problem. There are cryptographically secure PRNGs, but in general they aren't very good for video games or Monte Carlo (too slow).

    So what is your application?
     
  13. Jul 8, 2015 #12

    wle

    User Avatar

    This is all fixed in Java: ints are 32 bit signed two's complement integers that wrap around on overflow. It's not platform-dependent like in C.
     
  14. Jul 8, 2015 #13
    Endianness is consistent too, where in lower level languages, you have no guarentee
     
  15. Jul 8, 2015 #14

    jim mcnamara

    User Avatar

    Staff: Mentor

    this compiles as C code(gcc 3.4.2) : gcc -C -Wall kiss.c
    Code (Text):

    // unrolling this code so you can see it better.
    // file:kiss.c
    /* Implementation of a 32-bit KISS generator which uses no multiply instructions */
    static unsigned int x=123456789,
                        y=234567891,
                        z=345678912,
                        w=456789123,
                        c=0;  // c is zero here
    unsigned int JKISS32()
    {
      int t;
      y ^= (y<<5);
      y ^= (y>>7);
      y ^= (y<<22);
      t = z+w+c;    // c is still zero here
      z = w;
      c = t < 0;    // c becomes 0 or 1 here
      w = t&2147483647; // no c here
      x += 1411392427;  // no c here
      return x + y + w;
    }
     
    MY question is:
    Where does c have ANY effect on ANY calculation above as presented?
    Code (Text):
    c = t < 0;
    is dead code unless the c variable is used somewhere else.
    For example JKISS32() is called from a loop somewhere else we cannot see -- which is my guess.
    c varies from 0 to 1 depending on whether the t variable is negative or not negative assuming this code is called iteratively.
     
    Last edited: Jul 8, 2015
  16. Jul 8, 2015 #15

    wle

    User Avatar

    Well that's the point. c can be set to 1, which can affect subsequent calls of JKISS32().

    (In case you haven't read the whole thread, JKISS32() is meant to generate a pseudo-random sequence of numbers, so presumably it's going to be called more than once. Otherwise you may as well just do this.)
     
  17. Jul 8, 2015 #16

    D H

    User Avatar
    Staff Emeritus
    Science Advisor

    The current value of c impacts the output from JKISS32 via the calculation t = z+w+c. The updated value of c will affect the output from the next call to JKISS32(). This is a "Keep It Simple and Stupid" (hence the name) pseudo random number generator. Presumably it will be called many, many times during the course of an application's execution.
     
  18. Jul 8, 2015 #17
    Thanks all so far for your patiences.

    I've run the following with amendments suggested in this thread...

    Code (Text):

    public static void main(String[] args) {
            int x = 123456789, y = 234567891, z = 345678912, w = 456789123, c = 0, t;


            for (int i = 0; i < 10; i++) {
                y ^= (y << 5);
                y ^= (y >>> 7);                    // One > added from PF
                y ^= (y << 22);
                t = z + w + c;
                z = w;
                c = (t < 0) ? 1 : 0;               // 1 or 0 amendment from PF
                w = t & 2147483647;
                x += 1411392427;
                int next = x + y + w;
                System.out.println(next);
            }
        }
     
    which produces this output...

    -1714832263
    -368852369
    653136079
    -1337015847
    -162232845
    -312426689
    -302024013
    -538639081
    -639205643
    -541828828
    -204917723
    1413940082
    850185154
    -87394344
    -1847399219
    -563371111
    1218772128
    -1940900712
    -1922709363
    -1395979365

    This looks reasonable, if a little negative. Is there are chivalrous knight out there that might compile and execute the original C code for comparison? I don't have the resources to do so myself and I get a D in C.
     
  19. Jul 8, 2015 #18

    jim mcnamara

    User Avatar

    Staff: Mentor

    With regard to c - please note what I said later on. If the function were iterated it would have an effect, but did nothing to change the return value as presented.
    The question seemed to be posed from the point of view of: ignoring iteration for the benefit of learning.
     
  20. Jul 8, 2015 #19

    wle

    User Avatar

    Sure:
    Code (Text):
    $ clang jkiss.c
    $ ./a.out
    -1714832263
     -368852369
      653136079
    -1337015847
     -162232845
     -312426689
     -302024013
     -538639081
     -639205643
     -541828828
     -204917723
     1413940082
      850185154
      -87394344
    -1847399219
     -563371111
     1218772128
    -1940900712
    -1922709363
    -1395979365
    Exact code run:
    Code (C):
    #include <stdio.h>

    static unsigned int x = 123456789, y = 234567891,
                        z = 345678912, w = 456789123, c = 0;

    unsigned int jkiss32(void)
    {
        int t;
        y ^= y << 5;
        y ^= y >> 7;
        y ^= y << 22;
        t = z + w + c;
        z = w;
        c = t < 0;
        w = t & 2147483647;
        x += 1411392427;
        return x + y + w;
    }

    int main(void)
    {
        for (int i = 0; i < 20; ++i)
            printf("%11d\n", (int)jkiss32());
        return 0;
    }
    I printed the result as an int to compare the negative values.
     
    Last edited: Jul 8, 2015
  21. Jul 8, 2015 #20

    wle

    User Avatar

    You should also really consider structuring the Java code instead of dumping the JKISS algorithm in main(). Java annoyingly insists that you pretend your entire program is object-oriented even when it's not, and I haven't used it in about ten years, so I'm not sure what the best way to handle this is. One approach might be to make the random number generator a static function in its own class (my recollection is that the math library is or was implemented this way), pretending it's a namespace:
    Code (Java):
    import java.io.*;

    class JKISS {
        static int x = 123456789, y = 234567891,
                   z = 345678912, w = 456789123, c = 0;

        static int jkiss32() {
            int t;
            y ^= y << 5;
            y ^= y >>> 7;
            y ^= y << 22;
            t = z + w + c;
            z = w;
            c = (t < 0) ? 1 : 0;
            w = t & 2147483647;
            x += 1411392427;
            return x + y + w;
        }
    }

    class RngTest {
        public static void main(String[] s) {
            for (int i = 0; i < 20; ++i)
                System.out.format("%11d\n", JKISS.jkiss32());
        }
    }
    which you can run with java RngTest (after compiling this) from the console.
     
Know someone interested in this topic? Share this thread via Reddit, Google+, Twitter, or Facebook