Is float always rounding? - c

Here is my program, it turn decimal to base-"n", you can put number in "n" base what you want to turn to, it run successful but I have a question, I don't get it why the if ((float)input / (float)n <= 0) can pass in the fifth time. I'm debugging with vscode and watch the value every breakpoints and steps, here are the result
(run this line if ((float)input / (float)n <= 0))
input=20, n=2
First time : 20/2=10 (pass)
Second time : 10/2=5 (pass)
Third time : 5/2=2.5 (pass)
Forth time : 2.5/2=1 (pass) I don't understand why it is "1" not "1.25" (I think this is my main problem, is float always rouding ?)
Fifth time : 1/2=0.5 (pass)
Sixth time : 0.5/2=0 (fail and break)
Hope somebody can explain that I'll very appreciate, English not my mother tongue so forgive me.
#include <stdio.h>
#include <stdlib.h>
void rev(int num[]);
int cnt = 0;
int main()
{
int input = 20, num[10], i, n = 2;
// Decimal turn to base-n
printf("Decimal \"%d\" to base-%d = ", input, n);
for (i = 0; i < 10;)
{
if ((float)input / (float)n <= 0)
break;
else
{
num[i] = input % n;
input /= n;
i++;
cnt++;
}
}
rev(num);
printf("\n");
system("pause");
return 0;
}
void rev(int num[])
{
int i;
i = cnt - 1;
for (i; i >= 0; i--)
printf("%d", num[i]);
}

absolutely will be fail because . when you type casting float to int like int a = 3.14 ; just the decimal part will be stored exp int a = 0.5; means a equal to 0 .

When you divide input by n, you're doing integer division:
input /= n;
Integer division has an integer result. And either way, you're storing the result back to an integer, so any fractional portion is discarded.
So the values stored in input each time through the loop will be 20, 10, 5, 2 (not 2.5), 1, and 0.

Related

find sum of digits after decimal point

I want to find the sum of all the digits entered by a user after the decimal point in c.
Eg. 12.36 must return 9
15.06 must return 6
9.0 must return 0
My approach
#include <stdio.h>
int main()
{
double num,numfloat;
int digitf,numint,sumf=0;
scanf("%lf",&num);
numint=num;
numfloat=num-numint;
while(numfloat!=0)
{
digitf=(numfloat*10);
numfloat=numfloat*10-digitf;
sumf=sumf+digitf;
}
printf("Sum float %d",sumf);
return 0;
}
The sum comes out a lot more than the expected.
Try, (The reason why in this example, I haven't joined the loops is that: I want this to be usable on other situations where they use an alternate method of validating input, see the SECOND EXAMPLE for both loops joined):
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main() {
// read from stdin
char num[512] = { };
fgets(num, sizeof(num), stdin);
num[strcspn(num, "\n")] = '\0';
// verify if number is valid
int decimal_point_found = 0;
for (int i = 0; i < strlen(num); i++) {
// check if digit
if (!isdigit(num[i])) {
// be safe from multiple decimal points
if (num[i] == '.' && decimal_point_found == 0) {
decimal_point_found = 1;
continue;
}
printf("ERROR: enter a valid number\n");
return 1;
}
}
int total = 0;
// add all the decimal points
for (int i = 0, decimal_point_found = 0; i < strlen(num); i++) {
if (decimal_point_found == 1) {
total += num[i] - '0'; // - '0' converts char to int
}
if (num[i] == '.') {
decimal_point_found = 1;
}
}
// show total
printf("%d\n", total);
}
In the above, I have read char instead of reading float. I have read using fgets() which is safer than scanf().
Handling char makes it so much easier to calculate such things. As we know the number of digits, etc.
With both loops joined:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main() {
char num[512] = { };
fgets(num, 512, stdin);
num[strcspn(num, "\n")] = '\0';
// verify if number is valid
int decimal_point_found = 0;
int total = 0;
for (int i = 0; i < strlen(num); i++) {
if (!isdigit(num[i])) {
if (num[i] == '.' && decimal_point_found == 0) {
decimal_point_found = 1;
continue;
}
printf("ERROR: enter a valid number\n");
break;
}
if (decimal_point_found == 1) {
total += num[i] - '0';
}
}
printf("%d\n", total);
}
Original code fails as unless the fraction if exactly an integer/power-of-2, the input number, as decimal text, does not convert exactly to the same double. Instead num is the closet double possible. Yet that closest double may have many more digits when manipulated.
Further OP's numfloat=numfloat*10-digitf; injects repeated rounding errors.
Instead code needs to compensate for that rounding in some fashion.
the input has to be a number
Hmm, better to read in as a string, yet we can code a tolerable solution if we know the length of input by using "%n" to record the length of user input.
width below is the number of non-white-space characters in input. If we assume things like 1) sign only when negative, 2) no exponential 3) not infinity nor NAN, 4) no more than 15 significant digits 5) no more than 15 fraction digits --> then width will almost always*1 gives us what is needed to process num.
#include<stdio.h>
#include<math.h>
int sumFraction(void) {
int sum = 0;
double num;
int start, end;
if (scanf(" %n%lf%n", &start, &num, &end) != 1) {
return -1;
}
if (num == 0) {
return 0;
}
int width = end - start;
if (num < 0) {
num = -num;
width--;
}
int p10 = (int) log10(num);
width--; // Decrement for the '.'
if (width > 15) {
printf("Too many leading digits\n");
return -1;
}
width -= (p10 + 1);
// Only care about fractional part
double ipart;
num = modf(num, &ipart);
if (num == 0) {
return 0;
}
// assert(width >= 0);
num *= pow(10, width);
long long ival = llround(num); // Form an integer
while (width > 0) {
width--;
sum += ival % 10;
ival /= 10;
}
return sum;
}
int main() {
printf(" %d\n", sumFraction());
printf(" %d\n", sumFraction());
printf(" %d\n", sumFraction());
}
*1 IMO, code is not robust as the given limitation of not reading in as a string is not real for the real world. So here is a non-real solution.
You mentioned in a comment that the input has to be a number.
This first point to mention is that when coding, we are not manipulating such abstract things as numbers,
but imperfection representations of numbers. Think to the famous painting "This is not a pipe".
Same here, "This is not a number".
float, double and char* are all or can be all representations of numbers.
Depending on the context, one representation can be more suitable than others. Here, using a char* is the best solution, has no internal conversion error occurs.
Now, let us assume that the input format double is imposed by your professor.
Why is your code not working? Mainly because internally, the representation of the numbers is generally imperfect.
A small error can lead to a large error when converting a float to an integer.
For example, int i = 0.999999 will give i = 0.
The solution is to account for the internal error representation, by introducing a margin, e.g. eps = 1.0e-14,
when performing the float-to-integer conversion, or when testing if a number is equal to 0.
A difficulty is that the internal error is multiplied by 10 when the number is multiplied by 10. So the value of epshas to be updated accordingly.
Moreover, we have to take into accout that the mantissa provides a relative accurracy only, not an absolute one.
Therefore, the eps value must be increased when the number is large.
0.123456789 --> 45
19.1 -> 1
12.45e-36 -> 12
12345.973 -> 19
0.83 -> 11
#include <stdio.h>
int main() {
double num, numfloat;
int digitf, numint, sumf = 0;
double eps = 1.0e-14; // to deal with representation inaccuracy of numbers
if (scanf("%lf", &num) != 1) return 1;
printf("number in memory: %.20g\n", num);
if (num < 0.0) num = -num;
numint = (int) (num + eps);
numfloat = num - numint;
int deal_with_low_number = numint == 0;
while (numint) { // the mantissa only proposes a relative accurracy ...
eps *= 10;
numint /= 10;
}
while (numfloat > eps || deal_with_low_number) {
numfloat *= 10;
digitf = (int) (numfloat + eps);
numfloat -= digitf;
sumf = sumf + digitf;
if (digitf != 0) deal_with_low_number = 0;
if (!deal_with_low_number) eps *= 10;
}
printf("Sum float %d\n", sumf);
return 0;
}

C program to find integer closest to 10

I am writing a program that will take any number of integers. The program will end when the terminal 0 has been entered. It will then output the number closest to 10 (except for the terminal character). If there are several numbers closest to 10 then it should output the last number entered.
My current code does read the numbers from the input stream, but I don't know how to implement the logic so that the program will give me the number that is closest to 10.
I know, that I need to keep track of the minimum somehow in order to update the final result.
#include <stdio.h>
int main() {
int n = 1;
int number = 1;
int numberArray[n];
int resultArray[n];
int min;
int absMin;
int result;
int finalResult;
while (number != 0) {
scanf("%d", &number);
numberArray[n] = number;
n++;
}
for (int i = 0; i < n; i++) {
min = 10 - numberArray[i];
if (min < 0) {
absMin = -min;
}
else {
absMin = min;
}
resultArray[i] = absMin;
result = resultArray[0];
if (resultArray[i] < result) {
finalResult = resultArray[i];
}
}
printf("%d\n", finalResult);
return 0;
}
here's a simple code I wrote
One thing I must say is you can't simply declare an array with unknown size and that's what you have done. Even if the no. of elements can vary, you either take input the number of elements from the user OR (like below) create an array of 100 elements or something else according to your need.
#include <stdio.h>
#define _CRT_NO_WARNINGS
int main() {
int n = 0;
int number = 1;
int numberArray[100];
int resultArray[100];
int minNumber;
int *min;
do {
scanf("%d", &number);
numberArray[n] = number;
n++;
}
while (number != 0);
resultArray[0] = 0;
min = &resultArray[0];
minNumber = numberArray[0];
for (int i = 0; i < n-1; i++) {
if(numberArray[i]>=10){
resultArray[i] = numberArray[i] - 10;
}
if(numberArray[i]<10){
resultArray[i] = 10 - numberArray[i];
}
if(resultArray[i] <= *min){
min = &resultArray[i];
minNumber = numberArray[i];
}
}
printf("\n%d",minNumber);
return 0;
}
I have improved your script and fixed a few issues:
#include <stdio.h>
#include <math.h>
#include <limits.h>
int main()
{
int n;
int number;
int numberArray[n];
while (scanf("%d", &number) && number != 0) {
numberArray[n++] = number;
}
int currentNumber;
int distance;
int result;
int resultIndex;
int min = INT_MAX; // +2147483647
for (int i = 0; i < n; i++) {
currentNumber = numberArray[i];
distance = fabs(10 - currentNumber);
printf("i: %d, number: %d, distance: %d\n", i, currentNumber, distance);
// the operator: '<=' will make sure that it will update even if we already have 10 as result
if (distance <= min) {
min = distance;
result = currentNumber;
resultIndex = i;
}
}
printf("The number that is closest to 10 is: %d. It is the digit nr: %d digit read from the input stream.\n", result, resultIndex + 1);
return 0;
}
Reading from the input stream:
We can use scanf inside the while loop to make it more compact. Also, it will loop one time fewer because we don't start with number = 1 which is just a placeholder - this is not the input - we don't want to loop over that step.
I used the shorthand notation n++ it is the post-increment-operator. The operator will increase the variable by one, once the statement is executed (numberArray entry will be set to number, n will be increased afterwards). It does the same, in this context, as writing n++ on a new line.
Variables:
We don't need that many. The interesting numbers are the result and the current minimum. Of course, we need an array with the inputs as well. That is pretty much all we need - the rest are just helper variables.
Iteration over the input stream:
To get the result, we can calculate the absolute distance from 10 for each entry. We then check if the distance is less than the current minimum. If it is smaller (closer to 10), then we will update the minimum, the distance will be the new minimum and I have added the resultIndex as well (to see which input is the best). The operator <= will make sure to pick the latter one if we have more than one number that has the same distance.
I have started with the minimum at the upper bound of the integer range. So this is the furthest the number can be away from the result (we only look at the absolute number value anyway so signed number don't matter).
That's pretty much it.

Counting powers of 3 within a given range in C

I have to write a program that takes in two positive integers, start and end, where (1 < start < end). Then the program would look within this range [start, end] and count the number of powers of 3.
So, for example, if start is 2 and end is 10, the output would be 2. (as 3 and 9 are powers of 3).
Below is my code:
#include <stdio.h>
#include <math.h>
int main(void) {
int start, end, i, count = 0;
printf("Enter start and end: ");
scanf("%d %d", &start, &end);
for (i = start; i <= end; i++) {
if ((log(i) / log(3)) == floor((log(i) / log(3)))) {
printf("%d\n", i);
count++;
}
}
printf("Answer = %d\n", count);
return 0;
}
But, when I tried to run one of the test cases [3, 1000], the output is 5, when it should be 6.
3
9
27
81
729
Answer = 5
The number 243 is missing. Is there something wrong with my code?
The problem is you are using exact comparison of floating point numbers. Specifically, here:
if ((log(i)/log(3)) == floor((log(i)/log(3))))
Since log() and floor() return double, you're comparing without any tolerance two values which cannot be compared that way.
How should I do floating point comparison?
Your immediate problem has to do with the imprecision of floating point numbers, something that is generally well documented on the net, including various methods useful in fixing that problem.
However, I'm not actually going to bother referring you to them because the use of floating point is totally unnecessary here. There's a much more efficient way of doing this that involves only integers.
Rather than going through numbers in your range looking for powers of three using floating point operations, you would be better off going through powers of three (using just integer multiplication) looking for numbers in your range.
In pseudo-code, that would go something like:
powerOfThree = 1
while powerOfThree <= endRange:
if powerOfThree >= startRange:
print powerOfThree
powerOfThree = powerOfThree * 3
You could even make it more efficient by selecting a more suitable starting value for powerOfThree but, since there are only 40-odd powers of three in a 64 bit number, that's probably a waste of time.
When converting from pseudo-code to the more concrete C, you unfortunately come across the limitations of the datatypes in that language, specifically the fact that multiplication may result in overflow.
There are various ways you can avoid this this such as detecting that it's about to happen and exiting the loop early.
Given below is the function that you need, one which handles this issue, along with some test code which can be used for validating it.
#include <stdio.h>
#include <limits.h>
// I hate typing :-)
typedef unsigned long ULONG;
typedef unsigned int UINT;
static UINT countPowersOfThreeBetween (ULONG low, ULONG high) {
// Catch invalid params, just exit with zero.
if (low > high) return 0;
// Go through all powers of three.
ULONG powerOfThree = 1;
UINT count = 0;
do {
// If within your range, count it.
if ((powerOfThree >= low) && (powerOfThree <= high)) {
count++;
// printf ("DEBUG: got %lu\n", powerOfThree);
}
// Early exit if about to overflow.
if (ULONG_MAX / powerOfThree < 3) break;
// Advance to next power and continue if within range.
powerOfThree *= 3;
} while (powerOfThree <= high);
// Notify caller of count.
return count;
}
// Test function to make test suite easier.
static void testRange (ULONG low, ULONG high) {
UINT count = countPowersOfThreeBetween (low, high);
printf ("In range %lu..%lu, found %u occurrences\n", low, high, count);
}
// Test suite, add whatever you need.
int main (void) {
testRange (1000, 10);
testRange (0, 0);
testRange (9, 9);
testRange (3, 1000);
testRange (0, ULONG_MAX);
testRange (ULONG_MAX, ULONG_MAX);
return 0;
}
As you will see from the output, this gives the correct counts for various ranges:
In range 1000..10, found 0 occurrences
In range 0..0, found 0 occurrences
In range 9..9, found 1 occurrences
In range 3..1000, found 6 occurrences
In range 0..18446744073709551615, found 41 occurrences
In range 18446744073709551615..18446744073709551615, found 0 occurrences
And, if you uncomment the printf line in countPowersOfThreeBetween(), you'll also see the actual values detected.
Before choosing floating point types in the future, I strongly recommend you read this article entitled "What every computer scientist should know about floating-point arithmetic", by David Goldberg. It explains your problem(s) nicely, much better than I could have.
You don't actually need floating point (or negative integer) types here, so they should be avoided. Form your powers by multiplication, rather than addition:
#include <assert.h>
#include <limits.h>
#include <stdio.h>
int main(void){
unsigned int start, end, i, count = 0;
printf("Enter start and end: ");
int x = scanf("%u %u", &start, &end);
assert(x == 2); // XXX: INSERT PROPER ERROR HANDLING!
// find the first power greater than or equal to start
for (i = 1; i < start && UINT_MAX / 3 >= i; i *= 3);
// ... then count each one less than or equal to end
while (i <= end && UINT_MAX / 3 >= i) {
printf("%u\n", i);
i *= 3;
count++;
}
printf("Answer = %u\n", count);
}
Your problem is round-off error while float calculating in computer, the result of log(243)/log(3) is not exactly log3(243), where computer store approximate value of it. eg, in my 32bit computer, it is 4.99999999999999911182.
However, you have two ways to solve it,
use integer calculation instead of float.
simple mathematical transformation.
number of powers of 3 in [start, end] is equivalent to floor(log3(end)-log3(start))+1, wrote in c is
printf("answer:%d\n", (int)((log(1000)-log(3))/log(3))+1);
complete code:
#include <stdio.h>
#include <math.h>
int pow3(int n) {
int ret = 1;
while(n--) {
ret *= 3;
}
return ret;
}
int main() {
int a, start, end, answer;
scanf("%d%d", &start, &end);
a = (int)(log(start+0.5)/log(3));
//printf("%d,%d,%d\n", a, pow3(a), start);
if(start == end) answer = (start == pow3(a));
else answer = (int)((log(end+0.5)-log(start))/log(3))+1;
printf("answer = %d\n", answer);
}
Result:
Input[0]: 2 10
Output[0]: 2
Input[1]: 1 3
Output[1]: 2
Input[2]: 3 1000
Output[2]:6
Your program fails because of floating point precision issues.
Use integer arithmetics instead:
#include <limits.h>
#include <stdio.h>
int main(void) {
unsigned int start, end, i, count;
printf("Enter start and end: ");
if (scanf("%u %u", &start, &end) == 2) {
for (i = 1, count = 0; i <= end && i <= UINT_MAX / 3; i *= 3) {
if (i >= start) {
printf("%u\n", i);
count++;
}
}
printf("Answer = %u\n", count);
}
return 0;
}
A direct solution with floating point arithmetics is possible too:
#include <math.h>
#include <stdio.h>
int main(void) {
unsigned int start, end, count = 0;
printf("Enter start and end: ");
if (scanf("%u %u", &start, &end) == 2) {
if (end > 0 && end >= start) {
int start3 = (start <= 1) ? 0 : (int)(log(start - 0.5) / log(3));
int end3 = (int)(log(end + 0.5) / log(3));
count = end3 - start3;
}
printf("Answer = %u\n", count);
}
return 0;
}

Why is my to_base_n Program not working?

I need to write a C program which will read a number (in base 10) from user input and output it in any base which is a power of 2. The calculations have to be performed in one function, to_base_n, which takes the parameters num and base and prints the number in the respective base. As a validation check, the program also checks if the base is a power of two with the isPowerofTwo function.
The way the conversion is carried out is by means of long division which carries out the logic in the pseudocode below:
void to_base_n(int x, int n){
int r, i = 0
int digits[16]
while (x ≠ 0){
r = x mod n
x = x / n
digits[i] = r
i++
}
for (i = 0, i < 15, i++)
print digits[i]
}
Which I believe is arithmetically sound. But when I try to, for example, convert 82000 to base 4, I get the following output:
The large digits appearing are even bigger than num itself, so I figured the modulus cannot be entering the array properly (because ∀{x,n}; x mod n < x). I can't seem to find what's wrong with it. The full code is listed below.
#include <stdio.h>
#include <ctype.h>
#include <stdbool.h>
bool isPowerofTwo(int);
void to_base_n(int, int);
int main(){
//Variables
int num, base;
//Prompt
printf("Please enter a number in base 10: ");
scanf("%d", &num);
printf("Please enter a base (2^n) to convert it to: ");
scanf("%d", &base);
//Precaution
while(!isPowerofTwo(base)){
printf("That number is not a power of 2. Please try again: ");;
scanf("%d", &base);
}
if(isPowerofTwo(base)){
//Output
printf("The number %d (base 10) is equivalent to ", num);
to_base_n(num, base);
printf(" (base %d).", base);
}
//Return Statement
return 0;
}
//Checks if Base is a Power of Two
bool isPowerofTwo(int base){
while((base % 2 == 0) && base > 1){
base = base / 2;
if(base == 1){
return true;
break;
}
}
return false;
}
//to_base_n
void to_base_n(int x, int n){
int r, i = 0;
int digits[16];
while(x != 0){
r = x % n;
x = x / n;
digits[i] = r;
i++;
}
for(i = 0; i < 15; i++)
printf("%d|",digits[i]);
}
Can anyone help explain what's wrong with it?
The number 82000 in base 4 would be:
110001100
Which is exacly what you get. Your mistake is that:
They are printed backwards.
You are printing more digits than you should, so you print garbage.
You ignore the number of digits extracted with your pseudo code, so you print uninitialised elements of the array.
for (i = 0, i < 15, i++)
print digits[i]
And they are printed in reverse order. I suggest changing it to this
for (i = i - 1, i >= 0, i--)
print digits[i]
and as C code in your function
for(i = i - 1; i >= 0; i--)
printf("%d|",digits[i]);

Rounding off an integer to always end on 0

I'm making a program to calculate the number of perfect squares between 1 and another number, and I want the counter to take only the first number of the integer, and put 0 on the rest, e.g: Result of the calculation is 31, I want to display 30, if it's 190, then display 100, and so on.
int number;
int i = 1;
int perfectCounter = 0;
printf("Enter a number: ");
scanf("%d", &number);
while (i <= number) {
float tempSquare = sqrt(i);
int integerPart = tempSquare;
if (tempSquare == integerPart)
perfectCounter++;
i++;
}
printf("%d", perfectCounter);
That's the code that I have right now, if I insert 1000, it will display 31, and I want it to display 30, I can't think a solution for this.
Divide the number by the highest power of 10 below the number. Do this using integer arithmetic, so it gets the integer part of the division. Then multiply by the power of 10.
#include <math.h>
int powerOf10 = pow(10, (int)log10(perfectCounter));
int roundedCounter = (perfectCounter/powerOf10)*powerOf10;
printf("%d", roundedCounter);
You can use a function like this one to round your numbers. Basically what it does is it "chips away" one digit at a time until we are left with only one digit and then adds appropriate number of zeros to it:
int round(int _in){
int numDigits = 0;
while(_in > 9){
++numDigits;
_in /= 10;
}
int res = _in; // whatever is left would be the left-most digit
for(int i = 0; i < numDigits; ++i){
res *= 10;
}
return res;
}
Here's a simple solution with no math:
void print_rounded(int i) {
unsigned u = i;
if (i < 0) { putchar('-'); u = -i; }
char buf[2];
int n = snprintf(buf, 2, "%u", u);
for (putchar(buf[0]); --n; putchar('0')) {}
}
(In other words, print the first digit, and then print enough 0's to make up the length of the original number.)

Resources