So I just received my paper. its said if the input number is 0.001001001 (repeated) it's gonna print 0.001..., if it's 0.015015015, then 0.015... as a print, if the number is 998 its should be 0.998... my idea is to divide it into something like 2 pieces but im still cant figure its out. thanks
scanf("%f",&num1);
scanf("%f",&num2);
scanf("%f",&num3);
num1 = floor(1000*(num1/999))/1000;
num2 = floor(1000*(num2/999))/1000;
num3 = floor(1000*(num3/999))/1000;
printf("%.3f...\n",num1);
printf("%.3f...\n",num2);
printf("%.3f...\n",num3);
input = 3 integers that divide to 999, the value is below 999
output = the result, if the result repeated (0.001001001) then its going to print out 0.001...
sample :
input = output
3 = 0.003...
10 = 0.010...
998 = 0.998...
Note: I tried it with the floor so i guess there's something error about my logic
Since the value is below 999, 999 not included, just read the integer, and print it with 0.%03d...:
int num;
scanf("%d", &num);
printf("0.%03d...\n", num);
The conversion specification %03d will print the given integer in base-10, with leading zeroes prepended so that it is at least 3 characters wide. For 3, it will print 003, for 10 it will print 010 and for 976 it will print 976.
What you specifically cannot do this with are floats. Floats in your computer are binary numbers and they cannot precisely produce decimal fractions... nor can they do infinite precision.
Ifx is near some 0.abcabcabc... pattern, scale is by *999 and then /1000.
abc.abcabc... 1000x
- 0.abcabcabc... 1x
-------------------
abc. 999 x
/ 1000
-------------------
0.abc
Mathematically this works to exact 3 digits. Yet we are working with double.
double is usual encoded as binary64 and can not exactly represent, 0.001..., 0.015..., 0.998... and so the above idea will result in values very near the intended. The * 999 and / 1000 steps may impart a small departure from the mathematical result too.
int cajunb_print(double x) {
printf("(before %.*e) ", DBL_DECIMAL_DIG, x);
x = x * (1000 - 1) / 1000;
printf("(after %.*e) ", DBL_DECIMAL_DIG, x);
return printf("%.3f...\n", x);
}
int main(void) {
cajunb_print(0.001001001001001001);
cajunb_print(0.015015015015015015);
cajunb_print(0.998998998998998998);
return 0;
}
Output
(before 1.00100100100100099e-03) (after 1.00000000000000002e-03) 0.001...
(before 1.50150150150150149e-02) (after 1.49999999999999994e-02) 0.015...
(before 9.98998998998999022e-01) (after 9.97999999999999998e-01) 0.998...
Related
I am trying to reverse a two digit number, and I understand there may be better ways of doing this, but I am curious now why the way I chose does not work.
If I input 48, it produces 84 (a successful reversal).
If I input 84, it produces 38. If I input 47, it produces 64. These are just some examples of unsuccessful reversals.
int digit_one, digit_two, input;
float a, b;
printf("Enter a two-digit number: ");
scanf("%d", &input);
a = input * 0.1; // turns the two digit input figure into a float with a digit after the decimal point
digit_one = a; // turns the float into an integer, eliminating the digit after the decimal point
b = a - digit_one; // produces a float that has a 0 before the decimal point, and a digit after the decimal point
digit_two = b * 10; // moves the digit that was after the decimal point, to before the decimal point
printf("The reversal is: %d%d\n", digit_two, digit_one);
Thank you!
a - digit_one is a fractional number. If it's slightly less than the exact result (because for example 0.7 cannot be represented exactly as a float), then (a - digit_one) * 10 will be slightly less than the desired integer, and so digit_two will be one less than you expect.
You can avoid floating point, and write int digit_one, digit_two = input / 10, input % 10;
Working with floats is not the best approach here. With the input "84", b * 10 = 3.999996 which is 3 when you convert it to an integer.
This is a classic computer science problem with floats. Here are some links where this has been explained very well:
Is floating point math broken?
https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
Your problem can be solved differently:
int digit_one, digit_two, input, a, b;
printf("Enter a two-digit number: ");
scanf("%d", &input);
digit_one = input % 10;
digit_two = (input / 10) % 10;
printf("The reversal is: %d%d\n", digit_one, digit_two);
int result =0;
do{
result = (result * 10) + (input % 10);
input /= 10;
} while(input)
printf("The reversal is: %d\n", result);
You can print the 'result' variable to get any integer value irrespective of 2 digit or 3 digit
I am trying to write a program that outputs the number of the digits in the decimal portion of a given number (0.128).
I made the following program:
#include <stdio.h>
#include <math.h>
int main(){
float result = 0;
int count = 0;
int exp = 0;
for(exp = 0; int(1+result) % 10 != 0; exp++)
{
result = 0.128 * pow(10, exp);
count++;
}
printf("%d \n", count);
printf("%f \n", result);
return 0;
}
What I had in mind was that exp keeps being incremented until int(1+result) % 10 outputs 0. So for example when result = 0.128 * pow(10,4) = 1280, result mod 10 (int(1+result) % 10) will output 0 and the loop will stop.
I know that on a bigger scale this method is still inefficient since if result was a given input like 1.1208 the program would basically stop at one digit short of the desired value; however, I am trying to first find out the reason why I'm facing the current issue.
My Issue: The loop won't just stop at 1280; it keeps looping until its value reaches 128000000.000000.
Here is the output when I run the program:
10
128000000.000000
Apologies if my description is vague, any given help is very much appreciated.
I am trying to write a program that outputs the number of the digits in the decimal portion of a given number (0.128).
This task is basically impossible, because on a conventional (binary) machine the goal is not meaningful.
If I write
float f = 0.128;
printf("%f\n", f);
I see
0.128000
and I might conclude that 0.128 has three digits. (Never mind about the three 0's.)
But if I then write
printf("%.15f\n", f);
I see
0.128000006079674
Wait a minute! What's going on? Now how many digits does it have?
It's customary to say that floating-point numbers are "not accurate" or that they suffer from "roundoff error". But in fact, floating-point numbers are, in their own way, perfectly accurate — it's just that they're accurate in base two, not the base 10 we're used to thinking about.
The surprising fact is that most decimal (base 10) fractions do not exist as finite binary fractions. This is similar to the way that the number 1/3 does not even exist as a finite decimal fraction. You can approximate 1/3 as 0.333 or 0.3333333333 or 0.33333333333333333333, but without an infinite number of 3's it's only an approximation. Similarly, you can approximate 1/10 in base 2 as 0b0.00011 or 0b0.000110011 or 0b0.000110011001100110011001100110011, but without an infinite number of 0011's it, too, is only an approximation. (That last rendition, with 33 bits past the binary point, works out to about 0.0999999999767.)
And it's the same with most decimal fractions you can think of, including 0.128. So when I wrote
float f = 0.128;
what I actually got in f was the binary number 0b0.00100000110001001001101111, which in decimal is exactly 0.12800000607967376708984375.
Once a number has been stored as a float (or a double, for that matter) it is what it is: there is no way to rediscover that it was initially initialized from a "nice, round" decimal fraction like 0.128. And if you try to "count the number of decimal digits", and if your code does a really precise job, you're liable to get an answer of 26 (that is, corresponding to the digits "12800000607967376708984375"), not 3.
P.S. If you were working with computer hardware that implemented decimal floating point, this problem's goal would be meaningful, possible, and tractable. And implementations of decimal floating point do exist. But the ordinary float and double values any of is likely to use on any of today's common, mass-market computers are invariably going to be binary (specifically, conforming to IEEE-754).
P.P.S. Above I wrote, "what I actually got in f was the binary number 0b0.00100000110001001001101111". And if you count the number of significant bits there — 100000110001001001101111 — you get 24, which is no coincidence at all. You can read at single precision floating-point format that the significand portion of a float has 24 bits (with 23 explicitly stored), and here, you're seeing that in action.
float vs. code
A binary float cannot encode 0.128 exactly as it is not a dyadic rational.
Instead, it takes on a nearby value: 0.12800000607967376708984375. 26 digits.
Rounding errors
OP's approach incurs rounding errors in result = 0.128 * pow(10, exp);.
Extended math needed
The goal is difficult. Example: FLT_TRUE_MIN takes about 149 digits.
We could use double or long double to get us somewhat there.
Simply multiply the fraction by 10.0 in each step.
d *= 10.0; still incurs rounding errors, but less so than OP's approach.
#include <stdio.h>
#include <math.h> int main(){
int count = 0;
float f = 0.128f;
double d = f - trunc(f);
printf("%.30f\n", d);
while (d) {
d *= 10.0;
double ipart = trunc(d);
printf("%.0f", ipart);
d -= ipart;
count++;
}
printf("\n");
printf("%d \n", count);
return 0;
}
Output
0.128000006079673767089843750000
12800000607967376708984375
26
Usefulness
Typically, past FLT_DECMAL_DIG (9) or so significant decimal places, OP’s goal is usually not that useful.
As others have said, the number of decimal digits is meaningless when using binary floating-point.
But you also have a flawed termination condition. The loop test is (int)(1+result) % 10 != 0 meaning that it will stop whenever we reach an integer whose last digit is 9.
That means that 0.9, 0.99 and 0.9999 all give a result of 2.
We also lose precision by truncating the double value we start with by storing into a float.
The most useful thing we could do is terminate when the remaining fractional part is less than the precision of the type used.
Suggested working code:
#include <math.h>
#include <float.h>
#include <stdio.h>
int main(void)
{
double val = 0.128;
double prec = DBL_EPSILON;
double result;
int count = 0;
while (fabs(modf(val, &result)) > prec) {
++count;
val *= 10;
prec *= 10;
}
printf("%d digit(s): %0*.0f\n", count, count, result);
}
Results:
3 digit(s): 128
Following code is example of how to confirm if number entered is in specific range or not.
For example if I enter number say N then I want increment counter which says if it is in range of:
1-10
11-20
...
91-100
Here is the code snip from one of the text book:
#define MAXVAL 50
#define COUNTER 11
main ()
{
float value[MAXVAL];
int i, low, high;
static group[COUNTER] = {0,0,0,0,0,0,0,0,0,0,0}
*/READING AND COUNTING*/
for(i=0; i<MAXVAL; i++)
{
/* READING OF VALUES*/
scanf("%f", &value[i]);
/* COUNTING FREQUENCY OF GROUPS */
++group[ (int) (value[i]+0.5)/10] <<< I would like to understand how this will find if number is in specific ranges?
/* PRINTING OF FREQUENCY TABLE */
printf("\n");
printf(" GROUP RANGE FREQUENCY\N\N");
for(i=0; i< COUNTER; i++)
{
low = i*10;
if (i==10)
high =100;
else
high=low + 9;
printf( " %2d %3dto%3d %d)\n", i+1, low,high,group[i]);
}
}
What does this will do in above C program: ++group[ (int) (value[i]+0.5)/10]
Thanks
Examine the index of the group array:
[(int) (value[i]+0.5)/10]
This effectively takes the value scanned in from console input, adds .50, divide the sum by 10, then convert to an int. The better question is why do this at all?
The addition of 0.50 is to account for rounding. If value[i] is at or above a marign of 0.50 (such as 1.51, 2.50, 3.99, etc) this forces it to the next whole number (2.01, 3.00, 4.49).
Next, the division by 10. This apparently assumes the values being input are between 0.00 and exclusively less than 109.50. Dividing by 10 ensures these values will be between 0.00 and 10.00. This will, of course not work as soon as the console input is greater than 109.50.
Then the cast to (int). Straight forward enough. Kill the fraction off the float and manufacture your int.
Finally, assuming the input was in fact between 0.00 and exclusively less than 109.50, the counter matching the requisite range in the group[] array will be incremented by one.
Bottom line, it is a poor mechanism for trying to cluster input values into groups and updating counters within he appropriate range, and it will choke as soon as the input value is > 109.50.
Lets break it down for understanding it.
read ++group[ (int) (value[i]+0.5)/10] as:
I want to increment the index of group array by 1.
Which index?
It somehow depends on the value entered by user (value[i])
Why add 0.5 to it?
To round a floating number. more specifically to take the ceil() of that number
Why divide by 10?
Because your groups are of size 10.
Example:
User enters 11.
value[i] = 11 (float)
11 + 0.5 = 11.5 (float)
11.5 / 10 = 1.15 (float)
typecast 1.15 to int = 1 (int)
++group[1], increments group[1] by 1 and shows that 11 falls in group 1 i.e. 10 - 19
Another example:
User enters 9.
value[i] = 9 (float)
9 + 0.5 = 9.5 (float)
9.5 / 10 = 0.95 (float)
typecast 0.95 to int = 0 (int)
++group[0], increments group[0] by 1 and shows that 9 falls in group 0 i.e. 0 - 9
Another example:
User enters 9.1.
value[i] = 9.1 (float)
9.1 + 0.5 = 9.6 (float)
9.6 / 10 = 0.96 (float)
typecast 0.95 to int = 1 (int)
++group[1], increments group[1] by 1 and shows that 9.1 falls in group 1 i.e. 10 - 19
Note:
According to the code, your groups are 0-9, 10 - 19 ... and not 1 - 10, 11 - 20
um something like this:
Assuming group[0] = 0->10, group[1] = 11->20, group[2] = 21->30..
take an example float: 10.3
Applying the formula there, 10.8/10 ~= 1. Hence its in the range 10->20.
Take another example: 22.4
Applying the formula there, (22.4 + 0.5)/10 ~= 22.9/10 = 2. Hence its in the range 20->30. And so on. It will work for high = 100 and low = 0.
++group[ (int) (value[i]+0.5)/10] is
taking the float input value value[i],
rounding it to an int (int) (value[i]+0.5)
then dividing it by 10 to get a group index, and then
adding 1 ++group[...] to the group it belongs to.
In other words it is computing the number of values that fall between 0..9, 10..19, 20..29, ... 100..109, 110..119
This code is completely unsafe. If the input value is greater that than COUNTER * 10 or negative, then random bytes of memory will be written. Throw this code away or place some safety checks into it.
EDIT
Safety check, ignore input values that are out of range.
int g = (int) (value[i]+0.5) /10]
if (0 <= g && g < COUNT)
++group[g];
I am trying to truncate everything past the hundredths decimal. (13.4396 would be 13.43) Sholdn't it always or never work?
I have this formula that works 99%:
input = (( (double) ((int)(orgInput * 100)) ) / 100) ;
Then I have this formula sequence that is arithmetically equivalent:
input = (orgInput * 100);
input = (int) input;
input = (double) (input);
input = input / 100;
These inputs do not give the desired result (Formula truncates and round down, while the broken down steps output the desired result):
12.33
99.99
22.22
44.32
56.78
11.11
And then an even bigger mystery to me is why 33.30 does not work on either of them. Below is my program that runs continuously to demonstrate my problem.
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
double orgInput, input;
while (4!=3)
{
printf("Please enter the dollar amount (up to $100) => ");
scanf("%lf", &orgInput);
/* Truncates anything past hundredths place */
input = (orgInput * 100) ;
printf("\n1. input is %g \n ", input);
input = (int) input ;
printf("\n2. input is %g \n ", input);
input = (double) (input) ;
printf("\n3. input is %g \n", input);
input = input / 100 ;
printf("\n4. input is %.2lf \n", input);
input = (( (double) ((int)(orgInput * 100)) ) / 100) ;
printf("\nUsing the formula the input is %.2lf \n \n\n", input);
}
system("PAUSE");
return 0;
}
Thank you in advance!!!! P.S. Sorry for the formatting I am still getting used to stackoverflow
Key phrases:
Double to int conversion
Precision error
I think you are suffering from floating-point precision errors.
You should be able to fix this by doing:
const double epsilon = 1e-10; // Or some suitable small number
input = floor(orgInput * 100 + epsilon) / 100;
An alternative is to stop this from happening on input. Instead of reading in a double, you read a string and then parse that to get out the dollar and cents amount (cents being exactly 2 digits following the decimal point, if any). You can then ignore everything else.
In general, if you are working with money truncated to cents, you might be best to keep it in cents and use integers. Either that or round instead of truncate (for my above example, that would mean an epsilon of 0.5).
You need to understand that floats are represented in binary as:
2^(exponent) * mantissa
Exponent is a standard integer, but mantissa (a value between 1 and 2) is a number of bits where each bit represents a fraction: 1, 1/2, 1/4, 1/8, 1/16 and so on... Therefore it is not possible for the mantissa to represent certain values exactly, it will have an accuracy of +/- some fraction.
For example you mentioned 33.30. As a float 33.30 can only be: 2^5 * mantissa.
In this case the mantissa has to be 33.30/32 = 1.40625 exactly. But by making it out of the fractions the closest it can be is be is: 1.0406249999999999111821580299874767661094. So the actual value of the double is not 33.30, its 33.2999999999999971578290569595992565155029296875, which of course rounds DOWN to 33.29 when you do the type cast to integer.
The correct way to fix your program is not to scan in a float in the first place. You should be scanning in two integers seperated by decimal, and if scanf returns a value that indicates it did not scan two integers, then scan it as one integer for the case of a dollar only value.
Sadly, printf works by conversions to ints inside it and will not properly print any double precision floats that have more than 6 decimal places, which is why you see it as 33.30 even through you are asking printf to print the value of a double.
Most machines use binary, not decimal floating point. While binary-to-decimal conversion always gives exact values (in theory), it's impossible to convert from decimal to binary without rounding (I'm not considering the impractical case when numbers can have infinite number of digits).
As such, all your binary floating-point numbers are going to be slightly off of what they would've been in decimal.
The only 1-digit decimal fractions that can be represented in binary are: .0, .5.
Likewise, 2-digit decimal fractions exactly representable in binary are: .00, .25, .50, .75 (see here).
If you want, which I doubt, you can round to the nearest fraction of the four.
Could someone tell me why the following code is outputting 0 at the marked line?
It seems as if everything is correct but then when I try to get the result near the end it's giving me 0 each time.
#include <stdio.h>
int main() {
// Gather time-lapse variables
int frameRate, totalLengthSecs;
printf("How many frames per second: ");
scanf("%i", &frameRate);
printf("--> %i frames confirmed.", frameRate);
printf("\nDesired length of time-lapse [secs]: ");
scanf("%i", &totalLengthSecs);
printf("--> %i seconds confirmed.", totalLengthSecs);
int totalFrames = frameRate * totalLengthSecs;
printf("\nYou need %i frames.", totalFrames);
// Time-lapse interval calculation
int timeLapseInterval = totalLengthSecs / totalFrames;
printf("\n\n%i", timeLapseInterval); // <-- this prints 0
return 0;
}
In short: Integer division truncates
You need the following:
double timeLapseInterval = (double) totalLengthSecs / (double)totalFrames;
printf("\ntimeLapseInterval : %f \n", timeLapseInterval);
You are performing integer math.
Math between two integers will produce an integer. And the result will be rounded towards zero.
This line:
totalLengthSecs / totalFrames;
Is likely producing a result that's between 0 and 1. And getting rounded to 0
You are printing integers and therefore it will round down the value.
timeLapseInterval / totalFrames will be (1 / frameRate) which will be < 1 unless frameRate is 1 (or 0 in which case you have an error dividing by 0)
When you divide 2 numbers in C and the denominator is integer, the compiler intends it as an integer division. Therefore, if you divide 1 divided 2, it returns zero and not 0.5
Moreover, your output variable is an integer too, hence, if you expect decimal outputs, you won't get it.
You can fix it by doing:
float timeLapseInterval = totalLengthSecs / (float)totalFrames;
printf("\n\n%f", timeLapseInterval);
I hope this helps