omitting a printf causes an incorrect answer - c

For some reason I was getting a dramatically incorrect answer for a problem, so I put in this printf to try and debug.
for (s = 0; s <= 100; s++) {
for (t = 0; t <= 100; t++) {
printf("At (%f,%f), spl = %f\n", s, t, spl(loc_data, s, t)); */
if (spl(loc_data, s, t) > 80) {
p++;
}
}
}
If I omit the printf line, I get an incorrect answer. I think that it has something to do with memory allocation or uninitialised variables, but this is beyond my abilities. Any help would be appreciated.
Whole code:
#include <stdio.h>
#include <math.h>
typedef struct {
double x;
double y;
double W;
} data_t;
double spl(data_t *, double, double);
int main(int argc, char **argv) {
data_t loc_data[1000];
double spl0, p = 0, pp;
int i = 0, j = 0;
double s, t;
while (scanf("%lf %lf %lf", &loc_data[i].x, &loc_data[i].y, &loc_data[i].W) == 3) {
i++;
}
printf("\nStage 1\n=======\n");
printf("Number of sound sources: %d\n", i);
for (j = 0; j < i; j++) {
printf("%.1f meters east, %.1f meters north, power %1.5f Watts\n",
loc_data[j].x, loc_data[j].y, loc_data[j].W);
}
printf("\nStage 2\n=======\n");
spl0 = spl(loc_data, 0, 0);
printf("SPL at (0.0,0.0): %.1f dB\n", spl0);
printf("\nStage 3\n=======\n");
for (s = 0; s <= 100; s++) {
for (t = 0; t <= 100; t++) {
printf("At (%f,%f), spl = %f\n", s, t, spl(loc_data, s, t));
if (spl(loc_data, s, t) > 80) {
p++;
}
}
}
pp = p / 102.01;
printf("Points sampled: 10201\nAbove 80.0 dB: %.1f%%\n", pp);
return 0;
}
double spl(data_t *loc_data, double pointx, double pointy) {
int i = 0;
double r_sq, powi, spli, spl;
while (loc_data[i].W != 0) {
r_sq = pow(loc_data[i].x - pointx,2) + pow(loc_data[i].y - pointy,2);
powi = 10*log10(loc_data[i].W / pow(10,-12));
spli = powi + 10*log10((2 / (4 * M_PI * r_sq)) + (4 / (2.5 * M_PI * r_sq)));
spl = 10*log10(pow(10, spl/10) + pow(10, spli/10));
i++;
}
return spl;
}
Apologies for the poor formatting.

You''re using a variable (spl) before it's initialized inthe function spl():
double spl(data_t *loc_data, double pointx, double pointy) {
int i = 0;
double r_sq, powi, spli, spl;
while (loc_data[i].W != 0) {
r_sq = pow(loc_data[i].x - pointx,2) + pow(loc_data[i].y - pointy,2);
powi = 10*log10(loc_data[i].W / pow(10,-12));
spli = powi + 10*log10((2 / (4 * M_PI * r_sq)) + (4 / (2.5 * M_PI * r_sq)));
spl = 10*log10(pow(10, spl/10) + pow(10, spli/10));
// ^^^
i++;
}
return spl;
}
Calling printf() is probably influencing the value the variable happens to have.
Also, you read in a number of entries into the loc_data array, but don't pass that information to the spl() function. In spl() you treat the array entry with field W as the 'sentinel' - the end of the array. Is it a given that the last entry in the input data will have a zero value? If so, you should probably let us know, and probably check for that when done reading the input.

You are not initializing the loc_data entries in any way, which means they will contain garbage. After you scanf the entries (make sure to stop reading after you read 1000 lines), fill the remaining elements of the array with zeroes. I know you said you already tried this, but it's not visible in the code you posted.
Additionally, you should pass i (after giving it a better name) into the spl function so it knows how many good sources you have, instead of looking for a 0 as a terminator, which might not exist if you have 1000 good sources, or might exist too early if some source has a power of 0.

Related

C Keep Getting Double Free, despite trying to free in same form as allocation

Hey I'm trying to do a simple machine learning application for school but I keep getting double free for some reason I cannot even fathom.
float * evaluate(Network net,float * in)
{
int i,j;
float * out;
Neuron cur_neu;
for(i=0,j=0;i<net.n_lay;i++) j = net.lay_sizes[i]>j?net.lay_sizes[i]:j; //Calculating the maximum lay size for output storage
out = (float *) malloc(j*sizeof(float));
for(i=0;i<net.n_lay;i++) //Cycling through layers
{
for(j=0;j<net.lay_sizes[i];j++) //Cycling through Neurons
{
cur_neu=net.matrix[i][j];
out[j] = cur_neu.af(cur_neu.w,in,net.lay_sizes[i-1]); //Storing each answer in out
}
for(j=0;j<net.lay_sizes[i];j++) in[j] = out[j]; //Transfering answers to in
}
return out;
}
float loss(Network net, float **ins_orig, int t_steps)
{
float **profecies;
float st = .5f;
int d_steps = 4;
int t, i, j;
int out_size = net.lay_sizes[net.n_lay - 1];
int in_size = net.lay_sizes[0];
float out = 0.0f;
float **ins;
/*
d_steps = Divination Steps: Number of time steps forward the network has to predict.
The size of the output layer must be d_steps*#ins (deconsidering any conceptual i/os)
t_steps = Total of Steps: Total number of time steps to simulate.
*/
//Copying ins
ins = (float **)malloc(t_steps * sizeof(float *));
for (i = 0; i < t_steps; i++) //I allocate memory for and copy ins_orig to ins here
{
ins[i] = (float *)malloc(in_size * sizeof(float));
for (j = 0; j < in_size; j++)
ins[i][j] = ins_orig[i][j];
}
//
profecies = (float **)malloc(t_steps * sizeof(float *));
for (t = 0; t < t_steps; t++)
{
profecies[t] = evaluate(net, ins[t]);
/*
Profecy 0:
[[a1,b1,c1,d1]
[e1,f1,g1,h1]
[i1,j1,k1,l1]]
Profecy 1:
[[e2,f2,g2,h2]
[i2,j2,k2,l2]
[m2,n2,o2,q2]]
Verification for:
t=0:
loss+= abs(a1-ins[t][0]+b2-ins[t][1]...)
t=1:
t=0:
loss+= abs(e1-ins[t][0]+f2-ins[t][1]...)
*/
for (i = 0; i < d_steps; i++) //i is distance of prediction
{
if (i <= t) // stops negative profecy indexing
{
for (j = 0; j < in_size; j++)
{
out += (ins[t][j] - profecies[t-i][j+in_size*i]) * (ins[t][j] - profecies[t-i][j+in_size*i]) * (1 + st*i); //(1+st*i) The further the prediction, the bigger reward
}
}
}
}
//Free ins
for (i = 0; i < t_steps; i++) //I try to free it here, but to no avail
{
free(ins[i]);
}
free(ins);
return out;
}
I realize it's probably something very obvious but, I can't figure it out for the life of me and would appreciate the help.
Extra details that probably aren't necessary:
evaluate just passes the input to the network (stored in ins) and returns the output
both inputs and outputs are stored in float "matrixes"
Edit: Added evaluate
In your loss() you allocate the same number of floats for each ins:
ins[i] = (float *)malloc(in_size * sizeof(float));
In your evaluate() you calculate the longest lay_size, indicating that it may NOT be net.lay_sizes[0]:
for(i=0,j=0;i<net.n_lay;i++) j = net.lay_sizes[i]>j?net.lay_sizes[i]:j; //Calculating the maximum lay size for output storage
Then you are writing out-of-bounds here:
for(j=0;j<net.lay_sizes[i];j++) in[j] = out[j]; //Transfering answers to in
From that point, your memory is corrupted.

Why is the pointer to pointer arithmatic failing in my conditional statment?

sm is a 2D array of character pointers allocated dynamically. I need to understand why my pointer to pointer arithmetic is failing in conditional if in loop structure.
2nd column in sm is where the string is that I need to test with the grade key gk which is array of characters/string. s holds row size and q is column size for 2D array, hm is my heap memory counter for freeing function which is not importing for my question.
double *cals(char **sm, char *gk, int s, int q, unsigned *hm) {
int c = 0;
double *savg = malloc(s * sizeof(double));
assert(savg);
*hm += 1;
for (int i = 0; i < s; *(savg + i) = c / q * 100 , c = 0, ++i) {
for (int j = 0; j < q; ++j) {
if (*(*(sm + i * STUDENTATT + 1) + j) == *(gk + j))
++c;
}
}
return savg;
}
There isn't much information given about the purpose of cals function so I had to make a few assumptions to write this answer.
Assumption-1(meaningful):-
You want to find how much characters in the two strings are equal(no every characters) and then find the percentage of the same characters to the total characters. If that is the case use the below code.
double *cals(char **sm, char *gk, int s, int q, unsigned *hm) {
float c = 0; // To force float division the c is declared as a float variable
double *savg = malloc(s * sizeof(double));
assert(savg);
*hm += 1;
char* sm_i_key = NULL;
unsigned int strlen_gk = strlen(gk);
unsigned int key_length = string_gk;
for (int i=0; i<s; ++i) { //The calculation is moved inside for loop
sm_i_key = *(sm+i*q+1); // You can also use sm_i_key = &sm[i*q+1]
/* Uncomment this section if length of 2 strings are not bound to be equal
if(strlen(sm_i_key) < strlen_gk){
key_length = sm_i_key;
}
else{
key_length = strlen_gk
}
*/
for (int j = 0; j < key_length; ++j) {
if (sm_i_key[j] == gk[j])
++c;
}
savg [i] = c / strlen_gk * 100; /* Since gk is the grade key it is assumed
to be equal to the total number.*/
c = 0;
}
return savg;
}
Assumption-2:-
You want to check whether the strings whose starting address is stored in the second column of each row of a 2D array sm is equal to the string stored in array pointed by gk and then calculate a value(double).
The function cals only returns 0.0 or 100.0 as the formula avgs[i]=c / q * 100 will only produce 0 if stings are not equal(since integer division c/q will always result in 0 if c is less than q which is the case here) and 100 if strings are equal(Then why use a double to store the value if only 0 and 100 is stored).
If that is the case then what you are doing here is fine unless the array gk and array sm[i][2] have different string length(not q). It would be better to use strncmp to check the equality of string if the string length of two array's are bound to be different.
Use the below code to do that:-
double *cals(char **sm, char *gk, int s, int q, unsigned *hm) {
int c;
char* sm_i_key = NULL;
double *savg = malloc(s * sizeof(double));
assert(savg);
*hm += 1;
for (int i=0; i < s;++i){//The calculation is moved to a static assignment given below
if(strncmp(sm_i_key, gk, strlen(gk) == 0)
{
savg[i] = 100.0; // Since c/q * 100 => 100.0 if q == c
}
else
{
savg[i] = 0.0; /*Since c/q *100 => 0.0 if q < c since integer
division will result in 0.*/
}
}
return savg;
}
I hope it helps.

why Mergesort wall time is always 0? can someone help me pls...?

I am trying to implement merge sort algorithm and somehow I always get total_wall=0? Can someone please help me? Is there somehow, I miss, because I already double check the result of the mergesort and the array is already sorted after the sorting and in the initialized state, the array is not yet unsorted?
Thank before for your help.
this is my code:
int sorting (void) {
clock_t start_CPU, total_CPU;
time_t start_Wall, end_Wall, total_Wall;
start_CPU = clock ();
start_Wall = time (NULL);
sorting_partly(0, array_size - 1);
end_Wall = time (NULL);
total_CPU = clock () - start_CPU;
total_Wall = difftime (end_Wall, start_Wall);
printf ("total_cpu:\t %.3f \n", (float) total_CPU / CLOCKS_PER_SEC);
printf ("total_wall:\t %.3f\n", (float) total_Wall);
return 1;
}
int sorting_partly(int left, int right) {
int i = 0,accu = 0;
int length = right - left + 1;
int pivot = (left + right) / 2;
int merge1 = left, merge2 = pivot + 1;
int temp_array[length], temp_accu;
if (left == right) {
return 0;
} else {
sorting_partly (left, pivot); sorting_partly (pivot + 1, right);
}
for (accu = 0; accu <= pivot && accu + pivot + 1 <= right; accu++) {
if (array_input[merge1] <= array_input[merge2]) {
temp_array[accu] = array_input[merge1];
merge1++;
} else {
temp_array[accu] = array_input[merge2];
merge2++;
}
}
for (temp_accu = merge1; temp_accu <= pivot; temp_accu++) {
temp_array[accu] = array_input[temp_accu];
accu++;
}
for (temp_accu = merge2; temp_accu <= right; temp_accu++) {
temp_array[accu] = array_input[temp_accu];
accu++;
}
for (i = 0; i < length; i++) {
array_input[i + left] = temp_array[i];
}
return 1;
}
There are several potential issues:
time() returns the time in seconds, so it can't be used to measure short intervals.
difftime() returns double, and your code assigns the result to time_t (this can't really explain what you're seeing but IMO is worth fixing nonetheless).
The problem is this line:
total_Wall = difftime (end_Wall, start_Wall);
total_Wall is of type time_t which is probably an integral type, whilst difftime returns a double. You are probably getting a warning that you are loosing precision. Try changing total_Wall to double or float and see what happens.

Multiplying large numbers through strings

I'm trying to write a program that will receive 2 strings representing numbers of any length
(for instance, char *a = "10000000000000";, char *b = "9999999999999999";) and multiply them.
This is what I came up with so far, not sure how to continue (nullify simply fills the whole string with '0'):
char *multiply(char *hnum, const char *other)
{
int num1=0, num2=0, carry=0, hnumL=0, otherL=0, i=0, temp1L=0, temp2L=0, n=0;
char *temp1, *temp2;
if(!hnum || !other) return NULL;
for(hnumL=0; hnum[hnumL] != '\0'; hnumL++);
for(otherL=0; other[otherL] != '\0'; otherL++);
temp1 = (char*)malloc(otherL+hnumL);
if(!temp1) return NULL;
temp2 = (char*)malloc(otherL+hnumL);
if(!temp2) return NULL;
nullify(temp1);
nullify(temp2);
hnumL--;
otherL--;
for(otherL; otherL >= 0; otherL--)
{
carry = 0;
num1 = other[otherL] - '0';
for(hnumL; hnumL >= 0; hnumL--)
{
num2 = hnum[hnumL] - '0';
temp1[i+n] = (char)(((int)'0') + ((num1 * num2 + carry) % 10));
carry = (num1 * num2 + carry) / 10;
i++;
temp1L++;
}
if(carry > 0)
{
temp1[i+n] = (char)(((int)'0') + carry);
temp1L++;
}
p.s. Is there a library that handles this already? Couldn't find anything like it.
On paper, you would probably do as follows:
999x99
--------
8991
8991
========
98901
The process is to multiply individual digits starting from the right of each number and adding them up keeping a carry in mind each time ("9 times 9 equals 81, write 1, keep 8 in mind"). I'm pretty sure you covered that in elementary school, didn't you?.
The process can be easily put into an algorithm:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct result
{
int carry;
int res;
};
/*
* multiply two numbers between 0 and 9 into result.res. If there is a carry, put it into
* result.carry
*/
struct result mul(int a, int b)
{
struct result res;
res.res = a * b;
if (res.res > 9)
{
res.carry = res.res / 10;
res.res %= 10;
}
else
res.carry = 0;
return res;
}
/*
* add
* adds a digit (b) to str at pos. If the result generates a carry,
* it's added also (recursively)
*/
add(char str[], int pos, int b)
{
int res;
int carry;
res = str[pos] - '0' + b;
if (res > 9)
{
carry = res / 10;
res %= 10;
add(str, pos - 1, carry);
}
str[pos] = res + '0';
}
void nullify(char *numstr, int len)
{
while (--len >= 0)
numstr[len] = '0';
}
int main(void)
{
struct result res;
char *mp1 = "999";
char *mp2 = "999";
char sum[strlen(mp1) + strlen(mp2) + 1];
int i;
int j;
nullify(sum, strlen(mp1) + strlen(mp2));
for (i = strlen(mp2) - 1; i >= 0; i--)
{
/* iterate from right over second multiplikand */
for (j = strlen(mp1) - 1; j >= 0; j--)
{
/* iterate from right over first multiplikand */
res = mul((mp2[i] - '0'), (mp1[j] - '0'));
add(sum, i + j + 1, res.res); /* add sum */
add(sum, i + j, res.carry); /* add carry */
}
}
printf("%s * %s = %s\n", mp1, mp2, sum);
return 0;
}
This is just the same as on paper, except that you don't need to remember individual summands since we add up everything on the fly.
This might not bee the fastest way to do it, but it doesn't need malloc() (provided you have a C99 compiler, otherwise you would need to dynamically allocate sum) and works for arbitrarily long numbers (up to the stack limit since add() is implemented as recursive function).
Yes there are libraries that handle this. It's actually a pretty big subject area that a lot of research has gone into. I haven't looked through your code that closely, but I know that the library implementations of big num operations have very efficient algorithms that you're unlikely to discover on your own. FOr example, the multiplication routine we all learned in grade school (pre common-core) is a O(n^2) solution to multiplication, but there exist ways to solve it in ~O(n^1.5).
THe standard GNU c big num library is GNU MP
https://gmplib.org/

Avoid trailing zeroes in printf()

I keep stumbling on the format specifiers for the printf() family of functions. What I want is to be able to print a double (or float) with a maximum given number of digits after the decimal point. If I use:
printf("%1.3f", 359.01335);
printf("%1.3f", 359.00999);
I get
359.013
359.010
Instead of the desired
359.013
359.01
Can anybody help me?
This can't be done with the normal printf format specifiers. The closest you could get would be:
printf("%.6g", 359.013); // 359.013
printf("%.6g", 359.01); // 359.01
but the ".6" is the total numeric width so
printf("%.6g", 3.01357); // 3.01357
breaks it.
What you can do is to sprintf("%.20g") the number to a string buffer then manipulate the string to only have N characters past the decimal point.
Assuming your number is in the variable num, the following function will remove all but the first N decimals, then strip off the trailing zeros (and decimal point if they were all zeros).
char str[50];
sprintf (str,"%.20g",num); // Make the number.
morphNumericString (str, 3);
: :
void morphNumericString (char *s, int n) {
char *p;
int count;
p = strchr (s,'.'); // Find decimal point, if any.
if (p != NULL) {
count = n; // Adjust for more or less decimals.
while (count >= 0) { // Maximum decimals allowed.
count--;
if (*p == '\0') // If there's less than desired.
break;
p++; // Next character.
}
*p-- = '\0'; // Truncate string.
while (*p == '0') // Remove trailing zeros.
*p-- = '\0';
if (*p == '.') { // If all decimals were zeros, remove ".".
*p = '\0';
}
}
}
If you're not happy with the truncation aspect (which would turn 0.12399 into 0.123 rather than rounding it to 0.124), you can actually use the rounding facilities already provided by printf. You just need to analyse the number before-hand to dynamically create the widths, then use those to turn the number into a string:
#include <stdio.h>
void nDecimals (char *s, double d, int n) {
int sz; double d2;
// Allow for negative.
d2 = (d >= 0) ? d : -d;
sz = (d >= 0) ? 0 : 1;
// Add one for each whole digit (0.xx special case).
if (d2 < 1) sz++;
while (d2 >= 1) { d2 /= 10.0; sz++; }
// Adjust for decimal point and fractionals.
sz += 1 + n;
// Create format string then use it.
sprintf (s, "%*.*f", sz, n, d);
}
int main (void) {
char str[50];
double num[] = { 40, 359.01335, -359.00999,
359.01, 3.01357, 0.111111111, 1.1223344 };
for (int i = 0; i < sizeof(num)/sizeof(*num); i++) {
nDecimals (str, num[i], 3);
printf ("%30.20f -> %s\n", num[i], str);
}
return 0;
}
The whole point of nDecimals() in this case is to correctly work out the field widths, then format the number using a format string based on that. The test harness main() shows this in action:
40.00000000000000000000 -> 40.000
359.01335000000000263753 -> 359.013
-359.00999000000001615263 -> -359.010
359.00999999999999090505 -> 359.010
3.01357000000000008200 -> 3.014
0.11111111099999999852 -> 0.111
1.12233439999999995429 -> 1.122
Once you have the correctly rounded value, you can once again pass that to morphNumericString() to remove trailing zeros by simply changing:
nDecimals (str, num[i], 3);
into:
nDecimals (str, num[i], 3);
morphNumericString (str, 3);
(or calling morphNumericString at the end of nDecimals but, in that case, I'd probably just combine the two into one function), and you end up with:
40.00000000000000000000 -> 40
359.01335000000000263753 -> 359.013
-359.00999000000001615263 -> -359.01
359.00999999999999090505 -> 359.01
3.01357000000000008200 -> 3.014
0.11111111099999999852 -> 0.111
1.12233439999999995429 -> 1.122
To get rid of the trailing zeros, you should use the "%g" format:
float num = 1.33;
printf("%g", num); //output: 1.33
After the question was clarified a bit, that suppressing zeros is not the only thing that was asked, but limiting the output to three decimal places was required as well. I think that can't be done with sprintf format strings alone. As Pax Diablo pointed out, string manipulation would be required.
I like the answer of R. slightly tweaked:
float f = 1234.56789;
printf("%d.%.0f", f, 1000*(f-(int)f));
'1000' determines the precision.
Power to the 0.5 rounding.
EDIT
Ok, this answer was edited a few times and I lost track what I was thinking a few years back (and originally it did not fill all the criteria). So here is a new version (that fills all criteria and handles negative numbers correctly):
double f = 1234.05678900;
char s[100];
int decimals = 10;
sprintf(s,"%.*g", decimals, ((int)(pow(10, decimals)*(fabs(f) - abs((int)f)) +0.5))/pow(10,decimals));
printf("10 decimals: %d%s\n", (int)f, s+1);
And the test cases:
#import <stdio.h>
#import <stdlib.h>
#import <math.h>
int main(void){
double f = 1234.05678900;
char s[100];
int decimals;
decimals = 10;
sprintf(s,"%.*g", decimals, ((int)(pow(10, decimals)*(fabs(f) - abs((int)f)) +0.5))/pow(10,decimals));
printf("10 decimals: %d%s\n", (int)f, s+1);
decimals = 3;
sprintf(s,"%.*g", decimals, ((int)(pow(10, decimals)*(fabs(f) - abs((int)f)) +0.5))/pow(10,decimals));
printf(" 3 decimals: %d%s\n", (int)f, s+1);
f = -f;
decimals = 10;
sprintf(s,"%.*g", decimals, ((int)(pow(10, decimals)*(fabs(f) - abs((int)f)) +0.5))/pow(10,decimals));
printf(" negative 10: %d%s\n", (int)f, s+1);
decimals = 3;
sprintf(s,"%.*g", decimals, ((int)(pow(10, decimals)*(fabs(f) - abs((int)f)) +0.5))/pow(10,decimals));
printf(" negative 3: %d%s\n", (int)f, s+1);
decimals = 2;
f = 1.012;
sprintf(s,"%.*g", decimals, ((int)(pow(10, decimals)*(fabs(f) - abs((int)f)) +0.5))/pow(10,decimals));
printf(" additional : %d%s\n", (int)f, s+1);
return 0;
}
And the output of the tests:
10 decimals: 1234.056789
3 decimals: 1234.057
negative 10: -1234.056789
negative 3: -1234.057
additional : 1.01
Now, all criteria are met:
maximum number of decimals behind the zero is fixed
trailing zeros are removed
it does it mathematically right (right?)
works (now) also when first decimal is zero
Unfortunately this answer is a two-liner as sprintf does not return the string.
Why not just do this?
double f = 359.01335;
printf("%g", round(f * 1000.0) / 1000.0);
I search the string (starting rightmost) for the first character in the range 1 to 9 (ASCII value 49-57) then null (set to 0) each char right of it - see below:
void stripTrailingZeros(void) {
//This finds the index of the rightmost ASCII char[1-9] in array
//All elements to the left of this are nulled (=0)
int i = 20;
unsigned char char1 = 0; //initialised to ensure entry to condition below
while ((char1 > 57) || (char1 < 49)) {
i--;
char1 = sprintfBuffer[i];
}
//null chars left of i
for (int j = i; j < 20; j++) {
sprintfBuffer[i] = 0;
}
}
What about something like this (might have rounding errors and negative-value issues that need debugging, left as an exercise for the reader):
printf("%.0d%.4g\n", (int)f/10, f-((int)f-(int)f%10));
It's slightly programmatic but at least it doesn't make you do any string manipulation.
Some of the highly voted solutions suggest the %g conversion specifier of printf. This is wrong because there are cases where %g will produce scientific notation. Other solutions use math to print the desired number of decimal digits.
I think the easiest solution is to use sprintf with the %f conversion specifier and to manually remove trailing zeros and possibly a decimal point from the result. Here's a C99 solution:
#include <stdio.h>
#include <stdlib.h>
char*
format_double(double d) {
int size = snprintf(NULL, 0, "%.3f", d);
char *str = malloc(size + 1);
snprintf(str, size + 1, "%.3f", d);
for (int i = size - 1, end = size; i >= 0; i--) {
if (str[i] == '0') {
if (end == i + 1) {
end = i;
}
}
else if (str[i] == '.') {
if (end == i + 1) {
end = i;
}
str[end] = '\0';
break;
}
}
return str;
}
Note that the characters used for digits and the decimal separator depend on the current locale. The code above assumes a C or US English locale.
A simple solution but it gets the job done, assigns a known length and precision and avoids the chance of going exponential format (which is a risk when you use %g):
// Since we are only interested in 3 decimal places, this function
// can avoid any potential miniscule floating point differences
// which can return false when using "=="
int DoubleEquals(double i, double j)
{
return (fabs(i - j) < 0.000001);
}
void PrintMaxThreeDecimal(double d)
{
if (DoubleEquals(d, floor(d)))
printf("%.0f", d);
else if (DoubleEquals(d * 10, floor(d * 10)))
printf("%.1f", d);
else if (DoubleEquals(d * 100, floor(d* 100)))
printf("%.2f", d);
else
printf("%.3f", d);
}
Add or remove "elses" if you want a max of 2 decimals; 4 decimals; etc.
For example if you wanted 2 decimals:
void PrintMaxTwoDecimal(double d)
{
if (DoubleEquals(d, floor(d)))
printf("%.0f", d);
else if (DoubleEquals(d * 10, floor(d * 10)))
printf("%.1f", d);
else
printf("%.2f", d);
}
If you want to specify the minimum width to keep fields aligned, increment as necessary, for example:
void PrintAlignedMaxThreeDecimal(double d)
{
if (DoubleEquals(d, floor(d)))
printf("%7.0f", d);
else if (DoubleEquals(d * 10, floor(d * 10)))
printf("%9.1f", d);
else if (DoubleEquals(d * 100, floor(d* 100)))
printf("%10.2f", d);
else
printf("%11.3f", d);
}
You could also convert that to a function where you pass the desired width of the field:
void PrintAlignedWidthMaxThreeDecimal(int w, double d)
{
if (DoubleEquals(d, floor(d)))
printf("%*.0f", w-4, d);
else if (DoubleEquals(d * 10, floor(d * 10)))
printf("%*.1f", w-2, d);
else if (DoubleEquals(d * 100, floor(d* 100)))
printf("%*.2f", w-1, d);
else
printf("%*.3f", w, d);
}
I found problems in some of the solutions posted. I put this together based on answers above. It seems to work for me.
int doubleEquals(double i, double j) {
return (fabs(i - j) < 0.000001);
}
void printTruncatedDouble(double dd, int max_len) {
char str[50];
int match = 0;
for ( int ii = 0; ii < max_len; ii++ ) {
if (doubleEquals(dd * pow(10,ii), floor(dd * pow(10,ii)))) {
sprintf (str,"%f", round(dd*pow(10,ii))/pow(10,ii));
match = 1;
break;
}
}
if ( match != 1 ) {
sprintf (str,"%f", round(dd*pow(10,max_len))/pow(10,max_len));
}
char *pp;
int count;
pp = strchr (str,'.');
if (pp != NULL) {
count = max_len;
while (count >= 0) {
count--;
if (*pp == '\0')
break;
pp++;
}
*pp-- = '\0';
while (*pp == '0')
*pp-- = '\0';
if (*pp == '.') {
*pp = '\0';
}
}
printf ("%s\n", str);
}
int main(int argc, char **argv)
{
printTruncatedDouble( -1.999, 2 ); // prints -2
printTruncatedDouble( -1.006, 2 ); // prints -1.01
printTruncatedDouble( -1.005, 2 ); // prints -1
printf("\n");
printTruncatedDouble( 1.005, 2 ); // prints 1 (should be 1.01?)
printTruncatedDouble( 1.006, 2 ); // prints 1.01
printTruncatedDouble( 1.999, 2 ); // prints 2
printf("\n");
printTruncatedDouble( -1.999, 3 ); // prints -1.999
printTruncatedDouble( -1.001, 3 ); // prints -1.001
printTruncatedDouble( -1.0005, 3 ); // prints -1.001 (shound be -1?)
printTruncatedDouble( -1.0004, 3 ); // prints -1
printf("\n");
printTruncatedDouble( 1.0004, 3 ); // prints 1
printTruncatedDouble( 1.0005, 3 ); // prints 1.001
printTruncatedDouble( 1.001, 3 ); // prints 1.001
printTruncatedDouble( 1.999, 3 ); // prints 1.999
printf("\n");
exit(0);
}
Here is my first try at an answer:
void
xprintfloat(char *format, float f)
{
char s[50];
char *p;
sprintf(s, format, f);
for(p=s; *p; ++p)
if('.' == *p) {
while(*++p);
while('0'==*--p) *p = '\0';
}
printf("%s", s);
}
Known bugs: Possible buffer overflow depending on format. If "." is present for other reason than %f wrong result might happen.
Slight variation on above:
Eliminates period for case (10000.0).
Breaks after first period is processed.
Code here:
void EliminateTrailingFloatZeros(char *iValue)
{
char *p = 0;
for(p=iValue; *p; ++p) {
if('.' == *p) {
while(*++p);
while('0'==*--p) *p = '\0';
if(*p == '.') *p = '\0';
break;
}
}
}
It still has potential for overflow, so be careful ;P
I would say you should use
printf("%.8g",value);
If you use "%.6g" you will not get desired output for some numbers like.32.230210 it should print 32.23021 but it prints 32.2302
Hit the same issue, double precision is 15 decimal, and float precision is 6 decimal, so I wrote to 2 functions for them separately
#include <stdio.h>
#include <math.h>
#include <string>
#include <string.h>
std::string doublecompactstring(double d)
{
char buf[128] = {0};
if (isnan(d))
return "NAN";
sprintf(buf, "%.15f", d);
// try to remove the trailing zeros
size_t ccLen = strlen(buf);
for(int i=(int)(ccLen -1);i>=0;i--)
{
if (buf[i] == '0')
buf[i] = '\0';
else
break;
}
return buf;
}
std::string floatcompactstring(float d)
{
char buf[128] = {0};
if (isnan(d))
return "NAN";
sprintf(buf, "%.6f", d);
// try to remove the trailing zeros
size_t ccLen = strlen(buf);
for(int i=(int)(ccLen -1);i>=0;i--)
{
if (buf[i] == '0')
buf[i] = '\0';
else
break;
}
return buf;
}
int main(int argc, const char* argv[])
{
double a = 0.000000000000001;
float b = 0.000001f;
printf("a: %s\n", doublecompactstring(a).c_str());
printf("b: %s\n", floatcompactstring(b).c_str());
return 0;
}
output is
a: 0.000000000000001
b: 0.000001
I needed that and the first answer from paxdiablo does the trick. But I was not needing truncating and the version below is maybe slightly faster?
Starting to search end of string (EOS) after the ".", only one placement of EOS.
//https://stackoverflow.com/questions/277772/avoid-trailing-zeroes-in-printf
//adapted from paxdiablo (removed truncating)
char StringForDouble[50];
char *PointerInString;
void PrintDouble (double number) {
sprintf(StringForDouble,"%.10f",number); // convert number to string
PointerInString=strchr(&StringForDouble[0],'.'); // find decimal point, if any
if(PointerInString!=NULL) {
PointerInString=strchr(&PointerInString[0],'\0'); // find end of string
do{
PointerInString--;
} while(PointerInString[0]=='0'); // remove trailing zeros
if (PointerInString[0]=='.') { // if all decimals were zeros, remove "."
PointerInString[0]='\0';
} else {
PointerInString[1]='\0'; //otherwise put EOS after the first non zero char
}
}
printf("%s",&StringForDouble[0]);
}
My idea is to calculate the required precision that would not result in trailing zeroes for a given double value and pass it to the "%1.*f" format in printf().
This can even be done as one-liner:
int main() {
double r=1234.56789;
int precision=3;
printf(L"%1.*f", prec(r, precision), r);
}
int prec(const double& r, int precision)
{
double rPos = (r < 0)? -r : r;
double nkd = fmod(rPos, 1.0); // 0..0.99999999
int i, ex10 = 1;
for (i = 0; i < precision; ++i)
ex10 *= 10;
int nki = (int)(nkd * ex10 + 0.5);
// "Eliminate" trailing zeroes
int requiredPrecision = precision;
for (; requiredPrecision && !(nki % 10); ) {
--requiredPrecision;
nki /= 10;
}
return requiredPrecision;
}
And here is another %g solution. You should always provide a format precision that is "wide enough" (default is only 6) and round the value. I think this is a nice way to do it:
double round(const double &value, const double& rounding) {
return rounding!=0 ? floor(value/rounding + 0.5)*rounding : value;
}
printf("%.12g" round(val, 0.001)); // prints up to 3 relevant digits
Your code rounds to three decimal places due to the ".3" before the f
printf("%1.3f", 359.01335);
printf("%1.3f", 359.00999);
Thus if you the second line rounded to two decimal places, you should change it to this:
printf("%1.3f", 359.01335);
printf("%1.2f", 359.00999);
That code will output your desired results:
359.013
359.01
*Note this is assuming you already have it printing on separate lines, if not then the following will prevent it from printing on the same line:
printf("%1.3f\n", 359.01335);
printf("%1.2f\n", 359.00999);
The Following program source code was my test for this answer
#include <cstdio>
int main()
{
printf("%1.3f\n", 359.01335);
printf("%1.2f\n", 359.00999);
while (true){}
return 0;
}

Resources