• C

# printf/scanf and decimals

//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;
}
}
}

###### Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Commented:
@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
Commented:
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
Commented:
That works if we can assume the spacing is not negative
0
Author Commented:
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
Commented:
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 Commented:
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
Commented:
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 Commented:
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
Commented:
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 Commented:
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
Commented:
@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

Experts Exchange Solution brought to you by

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Commented:
> 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
Commented:
distance=10
width=3
pickets=8
0
Author Commented:
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
Commented:
:)

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

Dex*
0
###### It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C

From novice to tech pro — start learning today.