I am interested in computing the function int bit_Delta(double p1, double p2) for two doubles in the range [0,1). The function returns the index where the two doubles deviate in binary after the dot.
For example, 1/2 = 0.10 in binary, and 3/4=0.11 in binary. So bit_delta(0.5, 0.75) should return 2 because their first digit (1) is the same, but the second is the first digit where they differ.
I've thought about calculating the mantissa and exponent separately for each double. If the exponents are different, I think I can do it, but if the exponents are the same, I don't know how to use the mantissa. Any ideas?
One way would be to compare if both values are above 0.5 ==> both have the first bit set, else if both are below 0.5 ==> both have the first bit not set.
If both are above 0.5, subtract 0.5 and half the treshold, continue till you found the threshold, where the values are not both above or both below it.
#include <iostream>
int bit_delta(double a, double b)
{
if (a == b) return -1;
double treshold = 0.5;
for (int digit = 1; digit < 20; digit++, treshold /= 2)
{
if (a < treshold && b < treshold)
{
}
else if (a >= treshold && b >= treshold)
{
a -= treshold;
b -= treshold;
}
else
return digit;
}
return 20; //compare more than 20 digits does not make sense for a double
}
int main()
{
std::cout << bit_delta(0.25, 0.75) << std::endl;
std::cout << bit_delta(0.5, 0.75) << std::endl;
std::cout << bit_delta(0.7632, 0.751) << std::endl;
}
This code returns 1 2 7.
The following idea is based on conversion of the double values to fixed-point arithmetic, comparing the integers with XOR and counting the equal most significant bits.
#include <bit>
int bit_delta(double p1, double p2)
{
unsigned int i1 = static_cast<unsigned int>(p1 * 0x80000000U);
unsigned int i2 = static_cast<unsigned int>(p2 * 0x80000000U);
return std::countl_zero(i1 ^ i2);
}
It returns results between 1 .. 32.
With positive inputs p1 and p2 below 1. the MSB of i1 and i2 would always be zero, which is needed to get the counting right.
By using unsigned long long int instead of unsigned int you could increase the precision to 53 (i.e. the precision of double numbers).
The function countl_zero - included with the bit header - was introduced in C++20.
Related
I have a circle with points 0-360 the first and last point are connected, take point 11 and 216. Now, give any point how can i find if it is close to 11 or 216. I need a generic algorithm. For example:if given point 20 it should find that its close to 11, and when given 200 it should find close to 216. Till this point its easy but, for point 350 it should find that its close to 11, not 216.
I have this formula but it don't work for the third case:
int find_point(int a){
int temp1=(a>=11?a-11:11-a);
int temp2=(a>=216?a-216:216-a);
if(temp1<temp2)
return 11;
else
return 216;
}
That's the trick with the circle – it's round.
So, there are always two ways to get from one point on a circle to another, a left one and a right one. If the points are not on the same diameter than one way will be shorter than the other.
The other trick is that there is a wrap-around at 360° because 360° and 0° are actually the same angle (because, see above – the circle is round).
An example:
the minimum distance between 5° and 355°:
|355 - 5| = 350
but the correct answer would be 10.
If 360° is added to 5:
|355 - 365| = 10
Hence, my simple idea was to check a, a + 360, and a - 360. So, any wrap-around should be covered. There are some distances computed which might be even above of 360 but they will not hurt because the minimum is searched.
#include <algorithm>
#include <iostream>
int get_dist(int a, int b)
{
return std::min({ abs(a - b), abs(a + 360 - b), abs(a - 360 - b) });
}
int find_point(int a)
{
int d11 = get_dist(a, 11);
int d216 = get_dist(a, 216);
return d11 < d216 ? 11 : 216;
}
int main()
{
std::cout << "20 is closest to " << find_point(20) << '\n';
std::cout << "200 is closest to " << find_point(200) << '\n';
std::cout << "350 is closest to " << find_point(350) << '\n';
}
Output:
20 is closest to 11
200 is closest to 216
350 is closest to 11
Live Demo on coliru
Maybe, not the most elegant but a simple and maintenance-friendly solution (ignoring the magic numbers in the code).
Using some integer magic confined to addition, subtraction, and multiplication:
/* only for systems with 32-bit ints! */
int find_point(int a)
{
a*=11930465;
int distance_to_11 = a-131235112;
int distance_to_216 = a+1717986918;
if (distance_to_11 > 0) distance_to_11 = -distance_to_11; // -abs
if (distance_to_216 > 0) distance_to_216 = -distance_to_216; // -abs
int nearest;
if ( distance_to_216 > distance_to_11 ) {
nearest = 216;
} else {
nearest = 11;
}
return nearest;
}
The essence of this solution is to map the range [-180° ‒ +180°) to the range of a signed 32-bit integer. Once the mapping is done, one can make use of the natural modulo properties of 2's complement arithmetic.
Note: there is an error introduced in the mapping that will result in incorrect answers for values of a that are increasingly beyond the range of 0‒360. If that is of concern, the value of a should be confined to the range 0‒360.
Note: unlike abs(), the hand-coded -abs ensures a correct result regardless of the input since "The absolute value of the most negative number cannot be represented in two's complement." (see C11 draft).
Derivation of the constants is left as an exercise for the reader.
Here's an alternative 'generic' approach that trades modulo arithmetic and additional compares for some simple trig (instead of separate sin and cos, one could employ sincos if available):
#include <math.h>
int find_point(int a)
{
const double x11 = cos((double)11/180*M_PI);
const double y11 = sin((double)11/180*M_PI);
const double x216 = cos((double)216/180*M_PI);
const double y216 = sin((double)216/180*M_PI);
double x = cos((double)a/180*M_PI);
double y = sin((double)a/180*M_PI);
double square_of_distance_to_11 = (x-x11)*(x-x11) + (y-y11)*(y-y11);
double square_of_distance_to_216 = (x-x216)*(x-x216) + (y-y216)*(y-y216);
int nearest;
if ( square_of_distance_to_216 < square_of_distance_to_11 ) {
nearest = 216;
} else {
nearest = 11;
}
return nearest;
}
The code is reasonably self-explanatory. I'm exploiting the property that finding the nearest two points on a circle using the distance along the circle is equivalent to finding the nearest two point on a circle using the straight line distance between the points.
A bit of modulo and +/- trickery can avoid the use of min or max and eliminate the need to compare against additional alias points:
#include <stdlib.h>
int find_point(int a)
{
a = (a%360+360)%360; // clamp 'a' to 0..359
int distance_to_11 = abs((a-11+180+360)%360-180);
int distance_to_216 = abs((a-216+180+360)%360-180);
int nearest;
if ( distance_to_216 < distance_to_11 ) {
nearest = 216;
} else {
nearest = 11;
}
return nearest;
}
this is alternate solution. split circle into three parts as shown in picture. when the number is in green region answer is 11 directly, when the number is in yellow region compare between 11 and 216 and when the number is in blue region compare between 216 and ((360-number)+11)
int find_point(int a)
{
if(a>=0&&a<=11)
return 11;
else if(a>=11&&a<=216)
{
if((a-11)> (216-a))
return 216;
else
return 11;
}
else if(a>=216&&a<=360)
{
if((a-216)>(360-a+11))
return 11;
else
return 216;
}
else
return 0; //for invalid input
}
#include <stdio.h>
#define min(x,y) ((x)<(y)? (x) : (y))
int circle_dist(int a, int b)
{
a = (a%360+360)%360;
b = (b%360+360)%360;
return min(360-abs(a-b), abs(a-b));
}
int main(void) {
printf("%d (10)\n", circle_dist(10,20));
printf("%d (10)\n", circle_dist(20,10));
printf("%d (20)\n", circle_dist(350,10));
printf("%d (20)\n", circle_dist(10,350));
printf("%d (180)\n", circle_dist(310,130));
printf("%d (180)\n", circle_dist(130,310));
printf("%d (0)\n", circle_dist(1080,360));
printf("%d (0)\n", circle_dist(0,720));
return 0;
}
How can I get numerator and denominator from a fractional number? for example, from "1.375" i want to get "1375/1000" or "11/8" as a result. How can i do it with c++??
I have tried to do it by separating the numbers before the point and after the point but it doesn't give any idea how to get my desired output.
You didn't really specify whether you need to convert a floating point or a string to ratio, so I'm going to assume the former one.
Instead of trying string or arithmetic-based approaches, you can directly use properties of IEEE-754 encoding.
Floats (called binary32 by the standard) are encoded in memory like this:
S EEEEEEEE MMMMMMMMMMMMMMMMMMMMMMM
^ ^
bit 31 bit 0
where S is sign bit, Es are exponent bits (8 of them) Ms are mantissa bits (23 bits).
The number can be decoded like this:
value = (-1)^S * significand * 2 ^ expoenent
where:
significand = 1.MMMMMMMMMMMMMMMMMMMMMMM (as binary)
exponent = EEEEEEEE (as binary) - 127
(note: this is for so called "normal numbers", there are also zeroes, subnormals, infinities and NaNs - see Wikipedia page I linked)
This can be used here. We can rewrite the equation above like this:
(-1)^S * significand * exponent = (-1)^s * (significand * 2^23) * 2 ^ (exponent - 23)
The point is that significand * 2^23 is an integer (equal to 1.MMMMMMMMMMMMMMMMMMMMMMM, binary - by multiplying by 2^23, we moved the point 23 places right).2 ^ (exponent - 23) is an integer too, obviously.
In other words: we can write the number as:
(significand * 2^23) / 2^(-(exponent - 23)) (when exponent - 23 < 0)
or
[(significand * 2^23) * 2^(exponent - 23)] / 1 (when exponent - 23 >= 0)
So we have both numerator and denominator - directly from binary representation of the number.
All of the above could be implemented like this in C++:
struct Ratio
{
int64_t numerator; // numerator includes sign
uint64_t denominator;
float toFloat() const
{
return static_cast<float>(numerator) / denominator;
}
static Ratio fromFloat(float v)
{
// First, obtain bitwise representation of the value
const uint32_t bitwiseRepr = *reinterpret_cast<uint32_t*>(&v);
// Extract sign, exponent and mantissa bits (as stored in memory) for convenience:
const uint32_t signBit = bitwiseRepr >> 31u;
const uint32_t expBits = (bitwiseRepr >> 23u) & 0xffu; // 8 bits set
const uint32_t mntsBits = bitwiseRepr & 0x7fffffu; // 23 bits set
// Handle some special cases:
if(expBits == 0 && mntsBits == 0)
{
// special case: +0 and -0
return {0, 1};
}
else if(expBits == 255u && mntsBits == 0)
{
// special case: +inf, -inf
// Let's agree that infinity is always represented as 1/0 in Ratio
return {signBit ? -1 : 1, 0};
}
else if(expBits == 255u)
{
// special case: nan
// Let's agree, that if we get NaN, we returns max int64_t by 0
return {std::numeric_limits<int64_t>::max(), 0};
}
// mask lowest 23 bits (mantissa)
uint32_t significand = (1u << 23u) | mntsBits;
const int64_t signFactor = signBit ? -1 : 1;
const int32_t exp = expBits - 127 - 23;
if(exp < 0)
{
return {signFactor * static_cast<int64_t>(significand), 1u << static_cast<uint32_t>(-exp)};
}
else
{
return {signFactor * static_cast<int64_t>(significand * (1u << static_cast<uint32_t>(exp))), 1};
}
}
};
(hopefully comments and description above are understandable - let me know, if there's something to improve)
I've omitted checks for out of range values for simplicity.
We can use it like this:
float fv = 1.375f;
Ratio rv = Ratio::fromFloat(fv);
std::cout << "fv = " << fv << ", rv = " << rv << ", rv.toFloat() = " << rv.toFloat() << "\n";
And the output is:
fv = 1.375, rv = 11534336/8388608, rv.toFloat() = 1.375
As you can see, exactly the same values on both ends.
The problem is that numerators and denumerators are big. This is because the code always multiplies significand by 2^23, even if smaller value would be enough to make it integer (this is equivalent to writing 0.2 as 2000000/10000000 instead of 2/10 - it's the same thing, only written differently).
This can be solved by changing the code to multiply significand (and divide exponent) by minimum number, like this (ellipsis stands for parts which are the same as above):
// counts number of subsequent least significant bits equal to 0
// example: for 1001000 (binary) returns 3
uint32_t countTrailingZeroes(uint32_t v)
{
uint32_t counter = 0;
while(counter < 32 && (v & 1u) == 0)
{
v >>= 1u;
++counter;
}
return counter;
}
struct Ratio
{
...
static Ratio fromFloat(float v)
{
...
uint32_t significand = (1u << 23u) | mntsBits;
const uint32_t nTrailingZeroes = countTrailingZeroes(significand);
significand >>= nTrailingZeroes;
const int64_t signFactor = signBit ? -1 : 1;
const int32_t exp = expBits - 127 - 23 + nTrailingZeroes;
if(exp < 0)
{
return {signFactor * static_cast<int64_t>(significand), 1u << static_cast<uint32_t>(-exp)};
}
else
{
return {signFactor * static_cast<int64_t>(significand * (1u << static_cast<uint32_t>(exp))), 1};
}
}
};
And now, for the following code:
float fv = 1.375f;
Ratio rv = Ratio::fromFloat(fv);
std::cout << "fv = " << fv << ", rv = " << rv << ", rv.toFloat() = " << rv.toFloat() << "\n";
We get:
fv = 1.375, rv = 11/8, rv.toFloat() = 1.375
In C++ you can use the Boost rational class. But you need to give numerator and denominator.
For this you need to find out no of digits in the input string after the decimal point. You can do this by string manipulation functions. Read the input character by character and find no of characters after the .
char inputstr[30];
int noint=0, nodec=0;
char intstr[30], dec[30];
int decimalfound = 0;
int denominator = 1;
int numerator;
scanf("%s",inputstr);
len = strlen(inputstr);
for (int i=0; i<len; i++)
{
if (decimalfound ==0)
{
if (inputstr[i] == '.')
{
decimalfound = 1;
}
else
{
intstr[noint++] = inputstr[i];
}
}
else
{
dec[nodec++] = inputstr[i];
denominator *=10;
}
}
dec[nodec] = '\0';
intstr[noint] = '\0';
numerator = atoi(dec) + (atoi(intstr) * 1000);
// You can now use the numerator and denominator as the fraction,
// either in the Rational class or you can find gcd and divide by
// gcd.
What about this simple code:
double n = 1.375;
int num = 1, den = 1;
double frac = (num * 1.f / den);
double margin = 0.000001;
while (abs(frac - n) > margin){
if (frac > n){
den++;
}
else{
num++;
}
frac = (num * 1.f / den);
}
I don't really tested too much, it's only an idea.
I hope I'll be forgiven for posting an answer which uses "only the C language". I know you tagged the question with C++ - but I couldn't turn down the bait, sorry. This is still valid C++ at least (although it does, admittedly, use mainly C string-processing techniques).
int num_string_float_to_rat(char *input, long *num, long *den) {
char *tok = NULL, *end = NULL;
char buf[128] = {'\0'};
long a = 0, b = 0;
int den_power = 1;
strncpy(buf, input, sizeof(buf) - 1);
tok = strtok(buf, ".");
if (!tok) return 1;
a = strtol(tok, &end, 10);
if (*end != '\0') return 2;
tok = strtok(NULL, ".");
if (!tok) return 1;
den_power = strlen(tok); // Denominator power of 10
b = strtol(tok, &end, 10);
if (*end != '\0') return 2;
*den = static_cast<int>(pow(10.00, den_power));
*num = a * *den + b;
num_simple_fraction(num, den);
return 0;
}
Sample usage:
int rc = num_string_float_to_rat("0015.0235", &num, &den);
// Check return code -> should be 0!
printf("%ld/%ld\n", num, den);
Output:
30047/2000
Full example at http://codepad.org/CFQQEZkc .
Notes:
strtok() is used to parse the input in to tokens (no need to reinvent the wheel in that regard). strtok() modifies its input - so a temporary buffer is used for safety
it checks for invalid characters - and will return a non-zero return code if found
strtol() has been used instead of atoi() - as it can detect non-numeric characters in the input
scanf() has not been used to slurp the input - due to rounding issues with floating point numbers
the base for strtol() has been explicitly set to 10 to avoid problems with leading zeros (otherwise a leading zero will cause the number to be interpreted as octal)
it uses a num_simple_fraction() helper (not shown) - which in turn uses a gcd() helper (also not shown) - to convert the result to a simple fraction
log10() of the numerator is determined by calculating the length of the token after the decimal point
I'd do this in three steps.
1) find the decimal point, so that you know how large the denominator has to be.
2) get the numerator. That's just the original text with the decimal point removed.
3) get the denominator. If there was no decimal point, the denominator is 1. Otherwise, the denominator is 10^n, where n is the number of digits to the right of the (now-removed) decimal point.
struct fraction {
std::string num, den;
};
fraction parse(std::string input) {
// 1:
std::size_t dec_point = input.find('.');
// 2:
if (dec_point == std::string::npos)
dec_point = 0;
else {
dec_point = input.length() - dec_point;
input.erase(input.begin() + dec_point);
}
// 3:
int denom = 1;
for (int i = 1; i < dec_point; ++i)
denom *= 10;
string result = { input, std::to_string(denom) };
return result;
}
Say I have a floating point number. I would like to extract the positions of all the ones digits in the number's base 2 representation.
For example, 10.25 = 2^-2 + 2^1 + 2^3, so its base-2 ones positions are {-2, 1, 3}.
Once I have the list of base-2 powers of a number n, the following should always return true (in pseudocode).
sum = 0
for power in powers:
sum += 2.0 ** power
return n == sum
However, it is somewhat difficult to perform bit logic on floats in C and C++, and even more difficult to be portable.
How would one implement this in either of the languages with a small number of CPU instructions?
Give up on portability, assume IEEE float and 32-bit int.
// Doesn't check for NaN or denormalized.
// Left as an exercise for the reader.
void pbits(float x)
{
union {
float f;
unsigned i;
} u;
int sign, mantissa, exponent, i;
u.f = x;
sign = u.i >> 31;
exponent = ((u.i >> 23) & 255) - 127;
mantissa = (u.i & ((1 << 23) - 1)) | (1 << 23);
for (i = 0; i < 24; ++i) {
if (mantissa & (1 << (23 - i)))
printf("2^%d\n", exponent - i);
}
}
This will print out the powers of two that sum to the given floating point number. For example,
$ ./a.out 156
2^7
2^4
2^3
2^2
$ ./a.out 0.3333333333333333333333333
2^-2
2^-4
2^-6
2^-8
2^-10
2^-12
2^-14
2^-16
2^-18
2^-20
2^-22
2^-24
2^-25
You can see how 1/3 is rounded up, which is not intuitive since we would always round it down in decimal, no matter how many decimal places we use.
Footnote: Don't do the following:
float x = ...;
unsigned i = *(unsigned *) &x; // no
The trick with the union is far less likely to generate warnings or confuse the compiler.
There is no need to work with the encoding of floating-point numbers. C provides routines for working with floating-point values in a portable way. The following works.
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
/* This should be replaced with proper allocation for the floating-point
type.
*/
int powers[53];
double x = atof(argv[1]);
if (x <= 0)
{
fprintf(stderr, "Error, input must be positive.\n");
return 1;
}
// Find value of highest bit.
int e;
double f = frexp(x, &e) - .5;
powers[0] = --e;
int p = 1;
// Find remaining bits.
for (; 0 != f; --e)
{
printf("e = %d, f = %g.\n", e, f);
if (.5 <= f)
{
powers[p++] = e;
f -= .5;
}
f *= 2;
}
// Display.
printf("%.19g =", x);
for (int i = 0; i < p; ++i)
printf(" + 2**%d", powers[i]);
printf(".\n");
// Test.
double y = 0;
for (int i = 0; i < p; ++i)
y += ldexp(1, powers[i]);
if (x == y)
printf("Reconstructed number equals original.\n");
else
printf("Reconstructed number is %.19g, but original is %.19g.\n", y, x);
return 0;
}
I've searched all over the net, but I could not find a solution to my problem. I simply want a function that rounds double values like MS Excel does. Here is my code:
#include <iostream>
#include "math.h"
using namespace std;
double Round(double value, int precision) {
return floor(((value * pow(10.0, precision)) + 0.5)) / pow(10.0, precision);
}
int main(int argc, char *argv[]) {
/* The way MS Excel does it:
1.27815 1.27840 -> 1.27828
1.27813 1.27840 -> 1.27827
1.27819 1.27843 -> 1.27831
1.27999 1.28024 -> 1.28012
1.27839 1.27866 -> 1.27853
*/
cout << Round((1.27815 + 1.27840)/2, 5) << "\n"; // *
cout << Round((1.27813 + 1.27840)/2, 5) << "\n";
cout << Round((1.27819 + 1.27843)/2, 5) << "\n";
cout << Round((1.27999 + 1.28024)/2, 5) << "\n"; // *
cout << Round((1.27839 + 1.27866)/2, 5) << "\n"; // *
if(Round((1.27815 + 1.27840)/2, 5) == 1.27828) {
cout << "Hurray...\n";
}
system("PAUSE");
return EXIT_SUCCESS;
}
I have found the function here at stackoverflow, the answer states that it works like the built-in excel rounding routine, but it does not. Could you tell me what I'm missing?
In a sense what you are asking for is not possible:
Floating point values on most common platforms do not have a notion of a "number of decimal places". Numbers like 2.3 or 8.71 simply cannot be represented precisely. Therefore, it makes no sense to ask for any function that will return a floating point value with a given number of non-zero decimal places -- such numbers simply do not exist.
The only thing you can do with floating point types is to compute the nearest representable approximation, and then print the result with the desired precision, which will give you the textual form of the number that you desire. To compute the representation, you can do this:
double round(double x, int n)
{
int e;
double d;
std::frexp(x, &e);
if (e >= 0) return x; // number is an integer, nothing to do
double const f = std::pow(10.0, n);
std::modf(x * f, &d); // d == integral part of 10^n * x
return d / f;
}
(You can also use modf instead of frexp to determine whether x is already an integer. You should also check that n is non-negative, or otherwise define semantics for negative "precision".)
Alternatively to using floating point types, you could perform fixed point arithmetic. That is, you store everything as integers, but you treat them as units of, say, 1/1000. Then you could print such a number as follows:
std::cout << n / 1000 << "." << n % 1000;
Addition works as expected, though you have to write your own multiplication function.
To compare double values, you must specify a range of comparison, where the result could be considered "safe". You could use a macro for that.
Here is one example of what you could use:
#define COMPARE( A, B, PRECISION ) ( ( A >= B - PRECISION ) && ( A <= B + PRECISION ) )
int main()
{
double a = 12.34567;
bool equal = COMPARE( a, 12.34567F, 0.0002 );
equal = COMPARE( a, 15.34567F, 0.0002 );
return 0;
}
Thank you all for your answers! After considering the possible solutions I changed the original Round() function in my code to adding 0.6 instead of 0.5 to the value.
The value "127827.5" (I do understand that this is not an exact representation!) becomes "127828.1" and finally through floor() and dividing it becomes "1.27828" (or something more like 1.2782800..001). Using COMPARE suggested by Renan Greinert with a correctly chosen precision I can safely compare the values now.
Here is the final version:
#include <iostream>
#include "math.h"
#define COMPARE(A, B, PRECISION) ((A >= B-PRECISION) && (A <= B+PRECISION))
using namespace std;
double Round(double value, int precision) {
return floor(value * pow(10.0, precision) + 0.6) / pow(10.0, precision);
}
int main(int argc, char *argv[]) {
/* The way MS Excel does it:
1.27815 1.27840 // 1.27828
1.27813 1.27840 -> 1.27827
1.27819 1.27843 -> 1.27831
1.27999 1.28024 -> 1.28012
1.27839 1.27866 -> 1.27853
*/
cout << Round((1.27815 + 1.27840)/2, 5) << "\n";
cout << Round((1.27813 + 1.27840)/2, 5) << "\n";
cout << Round((1.27819 + 1.27843)/2, 5) << "\n";
cout << Round((1.27999 + 1.28024)/2, 5) << "\n";
cout << Round((1.27839 + 1.27866)/2, 5) << "\n";
//Comparing the rounded value against a fixed one
if(COMPARE(Round((1.27815 + 1.27840)/2, 5), 1.27828, 0.000001)) {
cout << "Hurray!\n";
}
//Comparing two rounded values
if(COMPARE(Round((1.27815 + 1.27840)/2, 5), Round((1.27814 + 1.27841)/2, 5), 0.000001)) {
cout << "Hurray!\n";
}
system("PAUSE");
return EXIT_SUCCESS;
}
I've tested it by rounding a hundred double values and than comparing the results to what Excel gives. They were all the same.
I'm afraid the answer is that Round cannot perform magic.
Since 1.27828 is not exactly representable as a double, you cannot compare some double with 1.27828 and hope it will match.
You need to do the maths without the decimal part, to get that numbers... so something like this.
double dPow = pow(10.0, 5.0);
double a = 1.27815;
double b = 1.27840;
double a2 = 1.27815 * dPow;
double b2 = 1.27840 * dPow;
double c = (a2 + b2) / 2 + 0.5;
Using your function...
double c = (Round(a) + Round(b)) / 2 + 0.5;
I have this static method, it receives a double and "cuts" its fractional tail leaving two digits after the dot. works almost all the time. I have noticed that when
it receives 2.3 it turns it to 2.29. This does not happen for 0.3, 1.3, 3.3, 4.3 and 102.3.
Code basically multiplies the number by 100 uses modf divides the integer value by 100 and returns it.
Here the code catches this one specific number and prints out:
static double dRound(double number) {
bool c = false;
if (number == 2.3)
c = true;
int factor = pow(10, 2);
number *= factor;
if (c) {
cout << " number *= factor : " << number << endl;
//number = 230;// When this is not marked as comment the code works well.
}
double returnVal;
if (c){
cout << " fractional : " << modf(number, &returnVal) << endl;
cout << " integer : " <<returnVal << endl;
}
modf(number, &returnVal);
return returnVal / factor;
}
it prints out:
number *= factor : 230
fractional : 1
integer : 229
Does anybody know why this is happening and how can i fix this?
Thank you, and have a great weekend.
Remember floating point number cannot represent decimal numbers exactly. 2.3 * 100 actually gives 229.99999999999997. Thus modf returns 229 and 0.9999999999999716.
However, cout's format will only display floating point numbers to 6 decimal places by default. So the 0.9999999999999716 is shown as 1.
You could use (roughly) the upper error limit that a value represents in floating point to avoid the 2.3 error:
#include <cmath>
#include <limits>
static double dRound(double d) {
double inf = copysign(std::numeric_limits<double>::infinity(), d);
double theNumberAfter = nextafter(d, inf);
double epsilon = theNumberAfter - d;
int factor = 100;
d *= factor;
epsilon *= factor/2;
d += epsilon;
double returnVal;
modf(number, &returnVal);
return returnVal / factor;
}
Result: http://www.ideone.com/ywmua
Here is a way without rounding:
double double_cut(double d)
{
long long x = d * 100;
return x/100.0;
}
Even if you want rounding according to 3rd digit after decimal point, here is a solution:
double double_cut_round(double d)
{
long long x = d * 1000;
if (x > 0)
x += 5;
else
x -= 5;
return x / 1000.0;
}