1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

beginner stuff

Discussion in 'C' started by kaporal_p, Jun 17, 2010.

  1. kaporal_p

    kaporal_p New Member

    Joined:
    Jun 17, 2010
    Messages:
    6
    Likes Received:
    0
    Trophy Points:
    0
    Hey,

    I'm a total beginner going through C for dummies, which seems to be a good starting point.

    I got to this exercise where I don't understand the output. It's a little program that calculates simple logs. here's the code

    Code:
    {
        double ln,x;
                       
        for(x=0.1;x<6.0;x+=0.1)               
        {
            ln = log(x);              
            printf("ln(%3.1f) = %f\n", x, ln);   
        }
        return(0);
    
    
    When I run the code the loop goes on through to 6.0. Why doesn't it stop at 5.9 since the 'test' is x<6.0?

    The way I think the for loop works is
    (initial condition; test; incrementation)
    where the initial condition is tested, if true it is applied in a function.
    THEN it is incremented and then the loop starts again. Is this wrong?

    Because if it's not, then why 6.0. I don't like this 6.0.

    Thanks
     
  2. shabbir

    shabbir Administrator Staff Member

    Joined:
    Jul 12, 2004
    Messages:
    15,292
    Likes Received:
    365
    Trophy Points:
    83
    In floating at times it is 5.999 and not 6.0 and see if that is the case. Precision is how you should use to loop with floats.
     
  3. kaporal_p

    kaporal_p New Member

    Joined:
    Jun 17, 2010
    Messages:
    6
    Likes Received:
    0
    Trophy Points:
    0
    Hi, thanks for answering,

    I'm not sur I understand what you mean.

    Do you mean there is uncertainty with float variables and that the value could oscillate between 5.999 and 6.0?

    But even if it is so, if for a fraction of a second it is 6.0 and it enters the loop at that moment, the loop shouldn't process it.

    Or do you mean the condition is oscillating between x<5.999 and x<6.0? But even then the loop should reject it.

    Sorry, I don't get it yet, could you push the explanation a little bit further?

    Thanks
     
  4. shabbir

    shabbir Administrator Staff Member

    Joined:
    Jul 12, 2004
    Messages:
    15,292
    Likes Received:
    365
    Trophy Points:
    83
    Does it loop for 6.1? My guess would be no.
     
  5. xpi0t0s

    xpi0t0s Mentor

    Joined:
    Aug 6, 2004
    Messages:
    3,012
    Likes Received:
    203
    Trophy Points:
    0
    Occupation:
    Senior Support Engineer
    Location:
    England
    On computers, numbers are stored in binary. And they have limited storage space, so when the conversion reaches that limit, it stops. Think of the decimal representations of fractions like 1/3 and 1/7 and now suppose that you had to write out 1/3 as precisely as possible using decimal representation...but only six significant figures. You would have to stop at 0.333333. Does 0.333333 = 1/3? No, of course not. 1/7=0.(142857) with the 142857 part repeated ad infinitum, so 0.142857 would be the six digit representation of 1/7 with the same problem.

    Try converting 0.1 to binary and you will see the problem. I'll get you started; the left hand column is the binary representation of 0.1:

    0 0.1<1
    . decimal/binary point
    0 0.1<0.5
    0 0.1<0.25
    0 0.1<0.125
    1 0.1>0.0625
    0 0.0375<0.03125
    1 0.0375>0.015625
    ... and see if this ever terminates. You can use a spreadsheet to make this easier.

    If it never terminates then there is a difference - an error - between the binary representation of 0.1 and 0.1 itself. And your loop multiplies this error by 60 by adding it to the loop variable sixty times.

    What's the solution? Floating point numbers are inaccurate, so you cannot say "if float1==float2" and expect the result to be meaningful. One solution is to allow for an error, for example your x only uses two significant figures so instead of the simplistic "x<6.0" you could do a subtraction and compare the result with an error term, such as "abs(x-6.0) < 0.001".

    A better solution in this case is to use integers (don't change x to int though) as they are more accurate than floats. Loop x from 1 to 60 and in the iteration use "x/10.0"; this way the error is not compounded as the loop progresses.

    By the way, your program wrongly assumes that ln==log. ln means log base e; it's the natural logarithm. log without a specified base is usually base 10.
     
  6. kaporal_p

    kaporal_p New Member

    Joined:
    Jun 17, 2010
    Messages:
    6
    Likes Received:
    0
    Trophy Points:
    0
    To shabbir: you guessed right, it does'nt loop for 6.1

    To xpi0t0s : I tried this
    Code:
    for(x=1;x<60;x+=1/10.0)
    and it works, but I have yet to grasp wher the magic happens...

    Since 1/10 is 0.1, isn't the result 0.1 what should become the iteration value, therefore as problematic as a straight 0.1? (is my question understandable???)

    Or is it because divider and dividend are both integers (1 and 10) ant that these are the values used by the loop as iteration 'agents'?

    But this brings another question, where are float values needed?

    As for ln = log(x). In the book I'm using, the author says :

    "The log() function computes the natural logarithm of a value."
    "The log10() function computes the base 10 logarithm for a value."

    So if this is the way C processes logs, in saying "ln = log(x)" I thought he was simply calculating the natural log of x "log(x)" and assingning it's value to the variable 'ln' for user understadability.

    Does that make sense?

    Thanks
     
  7. xpi0t0s

    xpi0t0s Mentor

    Joined:
    Aug 6, 2004
    Messages:
    3,012
    Likes Received:
    203
    Trophy Points:
    0
    Occupation:
    Senior Support Engineer
    Location:
    England
    That's not what I meant at all. Don't know why it works, it shouldn't, because you're now counting from 1 to 60 in tenths, so that should be around 600 iterations. What I meant was to count from 1 to 60 in 1's, as opposed to 0.1 to 6.0 in 0.1's, so in other words multiplying the whole lot by 10, then in the loop using x/10.0 instead of x as is currently the case.

    So what compiler are you using that thinks 60*10=60 instead of 600? An ancient one like Turbo C 3.0, which seems very popular for no obvious reason?

    ln/log, well I guess it depends on the math library you're using. If your math library uses log for ln and log10 for log that's fine. I was just saying the output should reflect reality.
     
  8. kaporal_p

    kaporal_p New Member

    Joined:
    Jun 17, 2010
    Messages:
    6
    Likes Received:
    0
    Trophy Points:
    0
    You're so right!

    When I ran the program, I just took a look at the last result, which wasn't 6.0 but 5.9 and thought everythink was fine... but there was in fact 600 iterations... oops

    So now I understand what you meant. And not only does it really work, but it's also a more elegant way of solving the problem.

    Thanks a lot.

    btw, I'm using the Vim compiler, for the colors!
     
  9. xpi0t0s

    xpi0t0s Mentor

    Joined:
    Aug 6, 2004
    Messages:
    3,012
    Likes Received:
    203
    Trophy Points:
    0
    Occupation:
    Senior Support Engineer
    Location:
    England
    Vim isn't a compiler, it's an editor. Don't confuse your tools. You edit programs with a text editor, then save and exit (recommended, cos if you shell out, then edit again, you can get into an interesting loop of confusion, especially if you forgot to save before shelling out, as in "hey, I fixed that!"). Compiling is done in several steps, often merged, but they are:

    preprocess, where lines starting with # are handled;
    compile, where C code is converted to object code (.o or .obj);
    link, where object files are joined together with libraries to create an executable.

    Preprocessing is often invoked directly by the compiler but some compilers allow you to invoke that stage separately, which is sometimes helpful (you won't need it yet though).
     
  10. kaporal_p

    kaporal_p New Member

    Joined:
    Jun 17, 2010
    Messages:
    6
    Likes Received:
    0
    Trophy Points:
    0
    So, I'm editing in Vim, then I run the programs in the command prompt (RUN cmd). Does that mean that the command prompt is a compiler? Does that mean there are more 'convivial' ways to run simple code than the little black square I'm now used to see? Could you please suggest one?

    Also, I'm learning C because I started doing Arduino projects and fast realized I needed to learn basic coding. In Arduino, you code and compile (and preprocess and link I guess)in the same 'interface', so, to me, it seems as if editing and compiling are joined for Arduino. Does this kind of programing environnement exist for C? Or is it better to have separate entities for reasons I have yet to understand?

    Thanks. I really appreciate your advices, especially since I'm getting started, it's easy to go in the wrong direction to realize it only a decade later...
     
  11. xpi0t0s

    xpi0t0s Mentor

    Joined:
    Aug 6, 2004
    Messages:
    3,012
    Likes Received:
    203
    Trophy Points:
    0
    Occupation:
    Senior Support Engineer
    Location:
    England
    What do you do between editing and running? There'll be a :w to save the file of course, but then what? (I assume we're talking about vim as "vi improved", if not then I'm probably talking pants).

    A compiler is a tool that converts C code into an executable. vim is a text editor, not a compiler. A shell is a shell, not a compiler. Maybe vim allows you to invoke a compiler with a : command of some kind, in which case vim is acting as an IDE (integrated development environment). IDE's batch stuff up for you so as to streamline the development process, for example in Visual Studio you can edit code then hit F5 to run it in a debugger: this will save the file(s), compile them, link them and start the debugger all in one keypress.

    If you're learning to program then you really need to understand the tools you're using. When editing a file in vim, save and exit, then invoke the compiler manually from the command line. It's a good idea to explore compiling and linking as two separate steps to get the hang of how it all works.
     
  12. kaporal_p

    kaporal_p New Member

    Joined:
    Jun 17, 2010
    Messages:
    6
    Likes Received:
    0
    Trophy Points:
    0
    Yes, it's Vi improved 7.2

    I edit, I save and then in comand prompt : gcc filename.c -o filename

    I do this like a robot of course, well not that blindly but almost. So I guess gcc is calling a compiler? but where it comes from I dunno, I never installed anything called gcc... -o seems to be what is converting the file to i/o I guess.

    So, gcc filename.c -o filename, would be : compiling then linking the file???

    Ok I guess I still have a bit of reading to do...

    Thanks
     
  13. xpi0t0s

    xpi0t0s Mentor

    Joined:
    Aug 6, 2004
    Messages:
    3,012
    Likes Received:
    203
    Trophy Points:
    0
    Occupation:
    Senior Support Engineer
    Location:
    England
    yep, there you go. gcc is a compiler: google it for more info. "gcc filename.c -o filename" compiles and links in one step to produce the executable "filename" directly from source "filename.c". If you save and exit with :wq then enter "gcc filename.c -o filename" directly at the shell prompt then you will see, providing it's on the PATH of course.
     

Share This Page