Solved

# printf/scanf and decimals

Posted on 2003-12-09
1,031 Views
//program to determine equal spacing for pickets

#include <stdio.h>    //scanf & printf
#include <conio.h>    //getch
# include <ctype.h>    //toupper

#define TRUE 1
#define FALSE !TRUE

char stay_open,c;

float distance,width,pickets,spacing,last_space;

void main()
{
stay_open = TRUE;
while (stay_open)
{
printf("\nEnter distance between posts  ");  // 45.8399
scanf ("%f",&distance);

printf("\nEnter width of picket  ");
scanf("%f",&width);                        //  1.5

printf("\nEnter desired number of pickets  ");
scanf("%f",&pickets);                          // 30

/*  The formula for determining how to evenly  space  pickets between 2 posts is:  */
spacing = ( (distance - (pickets * width) )  / (pickets + 1) );

/*  Using the above entries, the true value of "spacing" is .02709358.  Rounded off to .0271   (%.4f) */
printf("\n\nSpace pickets %.4f  ", spacing); //Space pickets .0271
//printf("\n\nSpace pickets %.8f  ", spacing);

/*  The formula for determining the measurement of the last space is:  */
last_space = ( distance - ( (pickets * spacing) + (pickets * width) ) );
/*Here is the problem to solve.  When determining the "last_space", the true value (.02709358) of "spacing" is not the correct value to use.  The value needed now is the "rounded off" value (%.4f .0271).  How can this be done? */
printf("\n\nLast space is %.4f  ", last_space);
//printf("\n\nLast space is %.8f  ", last_space);
printf("\n\nStay Open? Any key for YES, N for NO.");
c=toupper(getch());
if(c == 'N')
{
stay_open=!TRUE;
}
}
}

0
Question by:FrawgLips
• 5
• 4
• 2
• +2

LVL 19

Expert Comment

@FrawgLips:

> /*Here is the problem to solve.  When determining the "last_space", the true
> value (.02709358) of "spacing" is not the correct value to use.  The value
> needed now is the "rounded off" value (%.4f .0271).  How can this be done? */

Try this code:
spacing = (float)(((int)((spacing * 10000) + 0.5f)) / 10000);
printf("\n\nSpace pickets %.4f  ", spacing); //Space pickets .0271
last_space = ( distance - ( (pickets * spacing) + (pickets * width) ) );

Hope That Helps,
Dex*
0

LVL 44

Expert Comment

Dexstar's method is the one that I would have proposed as well. Just in case you are not clear on how it works:

The multiplication with 10000 "pulls" the four decimals you are interested in to the left side of the decimal point. After that you round the value by converting to an int (this will get rid of the fifth and so on decimal places). After that you divide by the same value that you first multiplied with to get back to the original value, but now rounded the way you wanted to. You can adjust the precision by e.g. using 100 to get two decimal places and so on.
0

LVL 84

Expert Comment

That works if we can assume the spacing is not negative
0

Author Comment

Thanks to all for response.

spacing = (float)(((int)((spacing * 10000) + 0.5f)) / 10000);

Dex*,   I cut and pasted  your code into mine....
the result was
"Space pickets .0000"
"Last space is .8399"
____________________
distance = 45.8399
width = 1.5
pickets = 30

Using a calculator and rounding off to 4 decimal places, the formula for spacing=.0271.  This is correct.

pickets * spacing = .813     (30 * .0271)
pickets * width = 45           (30 * 1.5)

45.8399 - 45.813 = .0269
(distance -  ( (pickets*spacing)+(pickets*width) ) )= .0269 this too is correct.
Can you be more precise as to how to convert a float to an int and do I need to replace ("float") ((("int")with variables  to obtain these results?

Thanks again,
FL

0

LVL 44

Expert Comment

OK, I finally compiled your program (I did change getch() to getchar(), because I don't have conio.h).
It does report the correct values, even without the explicit rounding. Both the "SPace pickets" and "Last space" is reported as 0.0271.
Does your compiler generate something different?
0

Author Comment

Yes, my compiler generates the same thing.   .0271 for both "spacing" and "last_space".  It is not totally correct though.  In this example "spacing" is correct but "last_space" should be .0269.  The problem is when "pickets" is multiplied by "spacing" because "spacing" is still an 8 digit decimal.......not rounded off to 4 decimal places.
For "last_space" to be correct, (pickets * spacing) should be
(30 * .0271).......not  (30 * .02709358).
In this example, all I want to see for "last_space" is .0269....how can that be accomplished using the 2 formulas shown previously?

Thanks,
FL

0

LVL 17

Expert Comment

They should be the same:

if      s = (d-pw)/(p+1);
=>   sp+s = d-pw;
=>   s = d - ps - pw;
=>   s = d - (ps + pw);
=>   s = (d - ((p  * s ) + (p * w) ) )    [Using C notation here]

s = spacing
d = distance
p = pickets
w = width
0

Author Comment

To double check the math:
multiply spacing (.0271) * pickets (30) = .813
Then add pickets (30) * width (1.5) = 45
Total is 45.813....subtracted from 45.8399 = .0269 (last_space).
There is always 1 space more than pickets....that's the reason for part of the formula being  ........ / (pickets +1).  OK, we have 31 spaces * .0271 = .8401.  Plus the space being taken up by the 30 pickets = 45 (30 * 1.5)
45 + .8401 = 45.8401 - 45.8399 = .0002.  Since 45.8401 > 45.8399 we know the last space will be .0002 smaller.

On the other hand, if we multiply the 31 spaces * .027093548(actual value)  = .8399.   + 45 = 45.3899.  Bingo! Right on...The problem is we are limited to 4 decimal places.  So, we must round off that 9 digit decimal (Not 8.  I gave the wrong actual value in my question) to 4 digits and then use the rounded off number for all further calculations.

I don't understand the (float)(((int) ........+ 0.5f....etc.

As you all can tell, I don't have the answer yet.  For anyone with further comments, suggestions etc: don't assume I know anything....spell it out....Thanks
FL

0

LVL 17

Expert Comment

I think your formula is wrong. Check my logic. The two expressions are equivalent.

if      s = (d-pw)/(p+1);
=>   sp+s = d-pw;             Multiply both sides by (p+1)
=>   s = d - ps - pw;          Subtract ps from both sides
=>   s = d - (ps + pw);       Use parenthesis... and this is your other expression, is it not?

It has been way too long since I was at school. Correct me if I'm wrong.
0

Author Comment

Look at your hand.  The thumb and little finger are the posts...you have 3 "pickets" and 4 spaces.  To determine the spacing you subtract the total width of all pickets from the distance between the posts then divide by 4. This gives the spacing.

To doublecheck you multiply the spacing * 3 (not 4) then add the total width of all pickets to that.  (spacing*pickets) +(pickets*width)
subtracted from distance between posts = the 4th space..... (last_space)....... (pickets+1) is used only for determining total spacing.

In most cases the last_space is not equal to any other space...this program is to determine what adjustments are necessary to get all pickets within .0001 of each other.  Sometimes only 1 picket needs adjusting.  Other times several may need adjusting.  It depends on how many .0001's difference there is between "spacing" and "last_space".  If  the difference is .0007 then 6 pickets need adjusted  by .0001 each. (adjusting 6 pickets changes 7 spaces)

The difference between the 2 (spacing  and  last_space) is the key to making this program work....I just need to zap about 5 decimal places after rounding off.

If you still think the formula is wrong, I won't wait for you to call me to build you a picket fence.....I will paint it for you though...lol

FL

0

LVL 19

Accepted Solution

Dexstar earned 250 total points
@FrawgLips:

Okay, there was a mistake in my answer before.  The line should read like this:
spacing = ((int)((spacing * 10000.0f) + 0.5f)) / 10000.0f;

If you can't understand what that line does, here it is written out as 4 lines:
spacing *= 10000.0f;
spacing += 0.5f;
spacing = (int)spacing;
spacing = spacing / 10000.0f;

Using 45.8399, 1.5, and 30 for the input values, here are the values of spacing at each step:
spacing = ( (distance - (pickets * width) )  / (pickets + 1) );      /* spacing = 0.027093580 */
spacing *= 10000.0f;                              /* spacing = 270.9358 */
spacing += 0.5f;                              /* spacing = 271.4358 */
spacing = (int)spacing;                        /* spacing = 271.0000 */
spacing = spacing / 10000.0f;                        /* spacing = 0.027100 */

When you cast a float as an Int, in drops off any decimal value that is there.  You add .5 to it so that it rounds properly when you chop off the decimal value.  The multiply by 10000 gets the digits you want to keep on the other side of the decimal so they don't get lost, and the divide by 10000 puts them back where they are supposed to go.

If you let the program run, this is the output:
Space pickets 0.0271
Last space is 0.0269

Isn't that correct?

Dex*

0

LVL 19

Expert Comment

> That works if we can assume the spacing is not negative

@ozo:  Give me an example where spacing could possibly be negative, and I'll rewrite to handle it.  :)

Peace,
Dex*
0

LVL 84

Expert Comment

distance=10
width=3
pickets=8
0

Author Comment

Good job Dex*,

Negative spacing is not a prob.  It would be the result of entering a wrong value or possibly trying to put too many pickets in between the posts in which case no code known to man could handle it...lol

Since I learned more than I asked for and it is the Holiday Season, have another 100 points....Happy Holidays to all....

FL
:o)
0

LVL 19

Expert Comment

:)

Thank you very much!  Glad you got what you wanted!

Dex*
0

## Featured Post

### Suggested Solutions

Why this code doesn't work? 8 93
Goodbye, so long 10 91
Connecting Native C / C++ to SQL Server 11 266
Unable to start eclipse ? 17 82
Have you thought about creating an iPhone application (app), but didn't even know where to get started? Here's how: ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ Important pre-programming comments: I’ve never tri…
Summary: This tutorial covers some basics of pointer, pointer arithmetic and function pointer. What is a pointer: A pointer is a variable which holds an address. This address might be address of another variable/address of devices/address of fu…
The goal of this video is to provide viewers with basic examples to understand and use nested-loops in the C programming language.
The goal of this video is to provide viewers with basic examples to understand opening and reading files in the C programming language.