• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1053
  • Last Modified:

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;
      printf("\nAdios");
      }
          }
}




0
FrawgLips
Asked:
FrawgLips
  • 5
  • 4
  • 2
  • +2
1 Solution
 
DexstarCommented:
@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
 
Karl Heinz KremerCommented:
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
 
ozoCommented:
That works if we can assume the spacing is not negative
0
The new generation of project management tools

With monday.com’s project management tool, you can see what everyone on your team is working in a single glance. Its intuitive dashboards are customizable, so you can create systems that work for you.

 
FrawgLipsAuthor 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
 
Karl Heinz KremerCommented:
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
 
FrawgLipsAuthor 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
 
rstaveleyCommented:
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
 
FrawgLipsAuthor 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
 
rstaveleyCommented:
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
 
FrawgLipsAuthor 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
 
DexstarCommented:
@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
 
DexstarCommented:
> 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
 
ozoCommented:
distance=10
width=3
pickets=8
0
 
FrawgLipsAuthor 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....

Greatly appreciate your efforts,
FL
 :o)  
0
 
DexstarCommented:
:)

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

Dex*
0

Featured Post

Has Powershell sent you back into the Stone Age?

If managing Active Directory using Windows Powershell® is making you feel like you stepped back in time, you are not alone.  For nearly 20 years, AD admins around the world have used one tool for day-to-day AD management: Hyena. Discover why.

  • 5
  • 4
  • 2
  • +2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now