cast double to int without rounding - c

i don't understand why when i try to cast my double to int the values ​​after the commas are rounded..
void print_float(double nb)
{
int negative;
int intpart;
double decpart = -10.754;
int v;
negative = (nb < 0.0f);
intpart = (int)nb;
decpart = nb - intpart;
v = (int)(decpart * 1000);
if (negative) {
v *= -1;
}
printf("%i.%i", intpart, v); // output: -10.753
}
I guess after thinking that the worries come from the cast, but I do not understand the problem..

A double cannot exactly encoded all numbers. It can exactly encoded about 264 different values. -10.754 is not one of them. Instead a nearby value is used just less than expected.
printf("%.24f", -10.754);
// -10.753999999999999559463504
The decpart * 1000 part introduces some imprecision yet the product is still below 754.0 and then the (int) cast makes that 753.

Related

Is there a function in C that can take the largest integral value of a variable?

I made a program that can get the largest integral of a float value:
#include <stdio.h>
float get_value(float a);
int main() {
float num = 4.58;
float new_val = get_value(num);
printf("%f \n", new_val);
}
float get_value(float a) {
int c = a;
for (int i = 0; i < 99; i++) {
a -= 0.01;
if (a == c) {
break;
}
}
return a;
}
It didn't work in the way I wanted it to be, so I want a shorthand of it instead of making a function.
So is there a function that I can use for this?
Use floor() if you want the lowest integer (closest to minus infinity) not exceeding the floating point value. Or use trunc() to get the smallest integer (closest to zero) not exceeding the magnitude of the fp value.
Also, note that .1 has a repeating representation in binary fp, so your function as written is always going to have problems. Just like 1/3 becomes .3333 in decimal.
You can use modf:
double integral, fractional;
double num = 4.58;
int result;
fractional = modf(num, &integral);
result = (int)integral;

How would I produce an integer from a float in the sense of removing the decimal point, despite floating-point precision errors?

In C, how can I produce, for example 314159 from 3.14159 or 11 from 1.1 floats? I may not use #include at all, and I am not allowed to use library functions. It must be completely cross platform, and fit in a single function.
I tried this:
while (Number-(int)Number) {
Number *= 10;
}
and this:
Number *= 10e6;
and floating-point precision errors get in my way. How can I do this? How can I accurately transform all digits in a float into an integer?
In response to a comment, they are a float argument to a function:
char *FloatToString(char *Dest, float Number, register unsigned char Base) {
if (Base < 2 || Base > 36 || !Dest) {
return (char *)0;
}
char *const RDest = Dest;
if (Number < 0) {
Number = -Number;
*Dest = '-';
Dest++;
}
register unsigned char WholeDigits = 1;
for (register unsigned int T = (int)Number/Base; T; T /= Base) {
WholeDigits++;
}
Dest[WholeDigits] = '.';
// I need to now effectively "delete" the decimal point to further process it. Don't answer how to convert a float to a string, answer the title.
return RDest;
}
The essential problem you have is that floating point numbers can't represent your example numbers, so your input is always going to be slightly different. So if you accurately produce output, it will be different from what you expect as the input numbers are different from what you think they are.
If you don't have to worry about very large numbers, you can do this most easily by converting to a long:
v = v - (long)v; // remove the integer part
int frac = (int)(v * 100000);
will give you the 5 digits after the decimal point. The problem with this is that it give undefined behavior if the initial value is too large to be converted to a long. You might also want to be rounding differently (converting to int truncates towards zero) -- if you want the closest value rather than the leading 5 digits of the fraction, you can use (int)(v * 100000 + (v > 0 ? 0.5 : -0.5))
New version :
#include <stdio.h>
int main()
{
double x;
int i;
char s[10];
x = 9999.12504;
x = (x-(int)x);
sprintf(s,"%0.5g\n",x);
sscanf((s+2),"%d",&i);
printf("%d",i);
return 0;
}
Old version
#include <stdio.h>
int main()
{
float x;
int i;
x = -3.14159;
x = (x-(int)x);
if (x>=0)
i = 100000*x;
else
i = -100000*x;
printf("%d",i);
return 0;
}
#include <stdio.h>
#include <stdint.h>
#include <limits.h>
int main(void) {
double t = 0.12;
unsigned long x = 0;
t = (t<0)? -t : t; // To handle negative numbers.
for(t = t-(int)t; x < ULONG_MAX/10; t = 10*t-(int)(10*t))
{
x = 10*x+(int)(10*t);
}
printf("%lu\n", x);
return 0;
}
Output:
11999999999999999644
I feel like you should use modulo to get the decimal portion, convert it to a string, count the number of characters, and use that to multiply your remainder before casting it to an int.

Calculation the Taylor series of sinh

The function calculates the value of sinh(x) using the following
development in a Taylor series:
I want to calculate the value of sinh(3) = 10.01787, but the function outputs 9. I also get this warning:
1>main.c(24): warning C4244: 'function': conversion from 'double' to 'int', possible loss of data
This is my code:
int fattoriale(int n)
{
int risultato = 1;
if (n == 0)
{
return 1;
}
for (int i = 1; i < n + 1; i++)
{
risultato = risultato * i;
}
return risultato;
}
int esponenziale(int base, int esponente)
{
int risultato = 1;
for (int i = 0; i < esponente; i++)
{
risultato = risultato * base;
}
return risultato;
}
double seno_iperbolico(double x)
{
double risultato = 0, check = -1;
for (int n = 0; check != risultato; n++)
{
check = risultato;
risultato = risultato + (((esponenziale(x, ((2 * n) + 1))) / (fattoriale((2 * n) + 1))));
}
return risultato;
}
int main(void)
{
double numero = 1;
double risultato = seno_iperbolico(numero);
}
Please help me fix this program.
It is actually pretty great that the compiler is warning you about this kind of data loss.
You see, when you call this:
esponenziale(x, ((2 * n) + 1))
You essentially lose your accuracy since you are converting your double, which is x, to an int. This is since the signature of esponenziale is int esponenziale(int base, int esponente).
Change it to double esponenziale(double base, int esponente), risultato should be a double as well, since you are returning it from the function and performing mathematical operations with/on it.
Remember that dividing a double with an int gives you a double back.
Edit: According to ringø's comment, and seeing how it actually solved your issue, you should also set double fattoriale(int n) and inside that double risultato = 1;.
You are losing precision since many of the terms will be fractional quantities. Using an int will clobber the decimal portion. Replace your int types with double types as appropriate.
Your factorial function will overflow for surprisingly small values of n. For 16 bit int, the largest value of n is 7, for 32 bit it's 12 and for 64 bit it's 19. The behaviour on overflowing a signed integral type is undefined. You could use unsigned long long or a uint128_t if your compiler supports it. That will buy you a bit more time. But given you're converting to a double anyway, you may as well use a double from the get-go. Note that an IEEE764 floating point double will hit infinity at 171!
Be assured that the radius of convergence of the Maclaurin expansion of sinh is infinite for any value of x. So any value of x will work, although convergence might be slow. See http://math.cmu.edu/~bkell/21122-2011f/sinh-maclaurin.pdf.

Getting the fractional part of a double value in integer without losing precision

i want to convert the fractional part of a double value with precision upto 4 digits into integer. but when i do it, i lose precision. Is there any way so that i can get the precise value?
#include<stdio.h>
int main()
{
double number;
double fractional_part;
int output;
number = 1.1234;
fractional_part = number-(int)number;
fractional_part = fractional_part*10000.0;
printf("%lf\n",fractional_part);
output = (int)fractional_part;
printf("%d\n",output);
return 0;
}
i am expecting output to be 1234 but it gives 1233. please suggest a way so that i can get desired output. i want the solution in C language.
Assuming you want to get back a positive fraction even for negative values, I'd go with
(int)round(fabs(value - trunc(value)) * 1e4)
which should give you the expected result 1234.
If you do not round and just truncate the value
(int)(fabs(value - trunc(value)) * 1e4)
(which is essentially the same as your original code), you'll end up with the unexpected result 1233 as 1.1234 - 1.0 = 0.12339999999999995 in double precision.
Without using round(), you'll also get the expected result if you change the order of operations to
(int)(fabs(value * 1e4 - trunc(value) * 1e4))
If the integral part of value is large enough, floating-point inaccuracies will of course kick in again.
You can also use modf() instead of trunc() as David suggests, which is probably the best approach as far as floating point accuracy goes:
double dummy;
(int)round(fabs(modf(value, &dummy)) * 1e4)
number= 1.1234, whole=1, fraction=1234
int main()
{
double number;
int whole, fraction;
number = 1.1234;
whole= (int)number;
fraction =(int)(number*10000);
fraction = fraction-(whole *10000);
printf("%d\n",fraction);
printf("%d\n",whole);
return 0;
}
A solution for any number could be:
#include <cmath>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
float number = 123.46244;
float number_final;
float temp = number; // keep the number in a temporary variable
int temp2 = 1; // keep the length of the fractional part
while (fmod(temp, 10) !=0) // find the length of the fractional part
{
temp = temp*10;
temp2 *= 10;
}
temp /= 10; // in tins step our number is lile this xxxx0
temp2 /= 10;
number_final = fmod(temp, temp2);
cout<<number_final;
getch();
return 0;
}
Use modf and ceil
#include <stdio.h>
#include <math.h>
int main(void)
{
double param, fractpart, intpart;
int output;
param = 1.1234;
fractpart = modf(param , &intpart);
output = (int)(ceil(fractpart * 10000));
printf("%d\n", output);
return 0;
}

How to get fractions in an integer division?

How do you divide two integers and get a double or float answer in C?
You need to cast one or the other to a float or double.
int x = 1;
int y = 3;
// Before
x / y; // (0!)
// After
((double)x) / y; // (0.33333...)
x / ((double)y); // (0.33333...)
Of course, make sure that you are store the result of the division in a double or float! It doesn't do you any good if you store the result in another int.
Regarding #Chad's comment ("[tailsPerField setIntValue:tailsPer]"):
Don't pass a double or float to setIntValue when you have setDoubleValue, etc. available. That's probably the same issue as I mentioned in the comment, where you aren't using an explicit cast, and you're getting an invalid value because a double is being read as an int.
For example, on my system, the file:
#include <stdio.h>
int main()
{
double x = 3.14;
printf("%d", x);
return 0;
}
outputs:
1374389535
because the double was attempted to be read as an int.
Use type-casting.
For example,
main()
{
float a;
int b = 2, c = 3;
a = (float) b / (float) c; // This is type-casting
printf("%f", a);
}

Resources