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;
}
Related
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.
I have a vector of numbers (floats), representing everything after the second of some time stamp. They have varying lengths. It looks something like this:
4456
485926
346
...
Representing 0.4456, 0.485926, and 0.346 seconds, respectively. I need to convert each of these to milliseconds, however I can’t simply multiply each by some constant since they’re all of different lengths. I’m fine with loosing accuracy, I just need the first 3 digits (the millisecond bit). How can this be done?
Try this:
#include <iostream>
#include <string>
using namespace std;
int getFirstThreeDigits(int number){
return stoi(to_string(number).substr(0,3));
}
int main()
{
float values[] = {4456, 485926, 346};
int arrLength = (sizeof(values)/sizeof(*values));
for( int i = 0 ; i < arrLength ; i++){
cout << getFirstThreeDigits(values[i]) << endl;
}
}
I'm assuming here that the integral portion of the float represents a subsecond value, so that 1234f is actually 0.1234 seconds. That seems to be what your question states.
If that's the case, it seems to me you can just continuously divide the value by ten until you get something less than one. Then multiply it by one thousand and round. That would go something like:
#include <iostream>
int millis(float value) {
if (value < 0) return -millis(-value);
//while (value >= 1000f) value /= 1000f;
while (value >= 1.0f) value /= 10.f;
return static_cast<int>(value * 1000 + .5f);
}
int main(int argc, char *argv[]) {
for (int i = 1; i < argc; ++i) {
float f= atof(argv[i]);
std::cout << " " << f << " -> " << millis(f) << "\n";
}
}
I've also put in a special case to handle negative number and a (commented-out, optional) optimisation to more quickly get down to sub-one for larger numbers.
A transcript follows with your example values:
pax> ./testprog 4456 485926 346
4456 -> 446
485926 -> 486
346 -> 346
If instead the values are already sub-second floats and you just want the number of milli-seconds, you do the same thing but without the initial divisions:
int millis(float value) {
if (value < 0) return -millis(-value);
return static_cast<int>(value * 1000 + .5f);
}
Using "(int)log10 + 1" is an easy way to get the number of integer digits
auto x = 485926;
auto len = (int)std::log10(x) + 1;
https://godbolt.org/z/v1jz7P
I'm working on this program that approximates a taylor series function. I have to approximate it so that the taylor series function stops approximating the sin function with a precision of .00001. In other words,the absolute value of the last approximation minus the current approximation equals less than or equal to 0.00001. It also approximates each angle from 0 to 360 degrees in 15 degree increments. My logic seems to be correct, but I cannot figure out why i am getting garbage values. Any help is appreciated!
#include <math.h>
#include <iomanip>
#include <iostream>
#include <string>
#include <stdlib.h>
#include <cmath>
double fact(int x){
int F = 1;
for(int i = 1; i <= x; i++){
F*=i;
}
return F;
}
double degreesToRadians(double angle_in_degrees){
double rad = (angle_in_degrees*M_PI)/180;
return rad;
}
using namespace std;
double mySine(double x){
int current =99999;
double comSin=x;
double prev=0;
int counter1 = 3;
int counter2 = 1;
while(current>0.00001){
prev = comSin;
if((counter2 % 2) == 0){
comSin += (pow(x,(counter1))/(fact(counter1)));
}else{
comSin -= (pow(x,(counter1))/(fact(counter1)));
}
current=abs(prev-comSin);
cout<<current<<endl;
counter1+=2;
counter2+=1;
}
return comSin;
}
using namespace std;
int main(){
cout<<"Angle\tSine"<<endl;
for (int i = 0; i<=360; i+=15){
cout<<i<<"\t"<<mySine(degreesToRadians(i));
}
}
Here is an example which illustrates how to go about doing this.
Using the pow function and calculating the factorial at each iteration is very inefficient -- these can often be maintained as running values which are updated alongside the sum during each iteration.
In this case, each iteration's addend is the product of two factors: a power of x and a (reciprocal) factorial. To get from one iteration's power factor to the next iteration's, just multiply by x*x. To get from one iteration's factorial factor to the next iteration's, just multiply by ((2*n+1) + 1) * ((2*n+1) + 2), before incrementing n (the iteration number).
And because these two factors are updated multiplicatively, they do not need to exist as separate running values, they can exists as a single running product. This also helps avoid precision problems -- both the power factor and the factorial can become large very quickly, but the ratio of their values goes to zero relatively gradually and is well-behaved as a running value.
So this example maintains these running values, updated at each iteration:
"sum" (of course)
"prod", the ratio: pow(x, 2n+1) / factorial 2n+1
"tnp1", the value of 2*n+1 (used in the factorial update)
The running update value, "prod" is negated every iteration in order to to factor in the (-1)^n.
I also included the function "XlatedSine". When x is too far away from zero, the sum requires more iterations for an accurate result, which takes longer to run and also can require more precision than our floating-point values can provide. When the magnitude of x goes beyond PI, "XlatedSine" finds another x, close to zero, with an equivalent value for sin(x), then uses this shifted x in a call to MaclaurinSine.
#include <iostream>
#include <iomanip>
// Importing cmath seemed wrong LOL, so define Abs and PI
static double Abs(double x) { return x < 0 ? -x : x; }
const double PI = 3.14159265358979323846;
// Taylor series about x==0 for sin(x):
//
// Sum(n=[0...oo]) { ((-1)^n) * (x^(2*n+1)) / (2*n + 1)! }
//
double MaclaurinSine(double x) {
const double xsq = x*x; // cached constant x squared
int tnp1 = 3; // 2*n+1 | n==1
double prod = xsq*x / 6; // pow(x, 2*n+1) / (2*n+1)! | n==1
double sum = x; // sum after n==0
for(;;) {
prod = -prod;
sum += prod;
static const double MinUpdate = 0.00001; // try zero -- the factorial will always dominate the power of x, eventually
if(Abs(prod) <= MinUpdate) {
return sum;
}
// Update the two factors in prod
prod *= xsq; // add 2 to the power factor's exponent
prod /= (tnp1 + 1) * (tnp1 + 2); // update the factorial factor by two iterations
tnp1 += 2;
}
}
// XlatedSine translates x to an angle close to zero which will produce the equivalent result.
double XlatedSine(double x) {
if(Abs(x) >= PI) {
// Use int casting to do an fmod PI (but symmetric about zero).
// Keep in mind that a really big x could overflow the int,
// however such a large double value will have lost so much precision
// at a sub-PI-sized scale that doing this in a legit fashion
// would also disappoint.
const int p = static_cast<int>(x / PI);
x -= PI * p;
if(p % 2) {
x = -x;
}
}
return MaclaurinSine(x);
}
double DegreesToRadians(double angle_deg) {
return PI / 180 * angle_deg;
}
int main() {
std::cout<<"Angle\tSine\n" << std::setprecision(12);
for(int i = 0; i<=360; i+=15) {
std::cout << i << "\t" << MaclaurinSine(DegreesToRadians(i)) << "\n";
//std::cout << i << "\t" << XlatedSine(DegreesToRadians(i)) << "\n";
}
}
In my program, I am trying to take the find the largest prime factor of the number 600851475143. I have made one for loop that determines all the factors of that number and stores them in a vector array. The problem I am having is that I don't know how to determine if the factor can be square rooted and give a whole number rather than a decimal. My code so far is:
#include <iostream>
#include <vector>
#include <math.h>
using namespace std;
vector <int> factors;
int main()
{
double num = 600851475143;
for (int i=1; i<=num; i++)
{
if (fmod(num,i)==0)
{
factors.push_back(i);
}
}
for (int i=0; i<factors.size(); i++)
{
if (sqrt(factor[i])) // ???
}
}
Can someone show me how to determine whether a number can be square rooted or not through my if statement?
int s = sqrt(factor[i]);
if ((s * s) == factor[i])
As hobbs pointed out in the comments,
Assuming that double is the usual 64-bit IEEE-754 double-precision float, for values less than 2^53 the difference between one double and the next representable double is less than or equal to 1. Above 2^53, the precision is worse than integer.
So if your int is 32 bits you are safe. If you have to deal with numbers bigger than 2^53, you may have some precision errors.
Perfect squares can only end in 0, 1, 4, or 9 in base 16, So for 75% of your inputs (assuming they are uniformly distributed) you can avoid a call to the square root in exchange for some very fast bit twiddling.
int isPerfectSquare(int n)
{
int h = n & 0xF; // h is the last hex "digit"
if (h > 9)
return 0;
// Use lazy evaluation to jump out of the if statement as soon as possible
if (h != 2 && h != 3 && h != 5 && h != 6 && h != 7 && h != 8)
{
int t = (int) floor( sqrt((double) n) + 0.5 );
return t*t == n;
}
return 0;
}
usage:
for ( int i = 0; i < factors.size(); i++) {
if ( isPerfectSquare( factor[ i]))
//...
}
Fastest way to determine if an integer's square root is an integer
The following should work. It takes advantage of integer truncation.
if (int (sqrt(factor[i])) * int (sqrt(factor[i])) == factor[i])
It works because the square root of a non-square number is a decimal. By converting to an integer, you remove the fractional part of the double. Once you square this, it is no longer equal to the original square root.
You also have to take into account the round-off error when comparing to cero. You can use std::round if your compiler supports c++11, if not, you can do it yourself (here)
#include <iostream>
#include <vector>
#include <math.h>
using namespace std;
vector <int> factors;
int main()
{
double num = 600851475143;
for (int i=1; i<=num; i++)
{
if (round(fmod(num,i))==0)
{
factors.push_back(i);
}
}
for (int i=0; i<factors.size(); i++)
{
int s = sqrt(factor[i]);
if ((s * s) == factor[i])
}
}
You are asking the wrong question. Your algorithm is wrong. (Well, not entirely, but if it were to be corrected following the presented idea, it would be quite inefficient.) With your approach, you need also to check for cubes, fifth powers and all other prime powers, recursively. Try to find all factors of 5120=5*2^10 for example.
The much easier way is to remove a factor after it was found by dividing
num=num/i
and only increase i if it is no longer a factor. Then, if the iteration encounters some i=j^2 or i=j^3,... , all factors j, if any, were already removed at an earlier stage, when i had the value j, and accounted for in the factor array.
You could also have mentioned that this is from the Euler project, problem 3. Then you would have, possibly, found the recent discussion "advice on how to make my algorithm faster" where more efficient variants of the factorization algorithm were discussed.
Here is a simple C++ function I wrote for determining whether a number has an integer square root or not:
bool has_sqrtroot(int n)
{
double sqrtroot=sqrt(n);
double flr=floor(sqrtroot);
if(abs(sqrtroot - flr) <= 1e-9)
return true;
return false;
}
As sqrt() function works with floating-point it is better to avoid working with its return value (floating-point calculation occasionally gives the wrong result, because of precision error). Rather you can write a function- isSquareNumber(int n), which will decide if the number is a square number or not and the whole calculation will be done in integer.
bool isSquareNumber(int n){
int l=1, h=n;
while(l<=h){
int m = (l+h) / 2;
if(m*m == n){
return true;
}else if(m*m > n){
h = m-1;
}else{
l = m+1;
}
}
return false;
}
int main()
{
// ......
for (int i=0; i<factors.size(); i++){
if (isSquareNumber(factor[i]) == true){
/// code
}
}
}
I needed to convert a fractional part of a number into integer without a comma,
for example I have 3.35 I want to get just 35 part without zero or a comma,
Because I used the modf() function to extract the the fractional part but it gives me a 0.35
if there is any way to do that or to filter the '0.' part I will be very grateful if you show me how with the smaller code possible,
A bit more efficient than converting to a string and back again:
int fractional_part_as_int(double number, int number_of_decimal_places) {
double dummy;
double frac = modf(number,&dummy);
return round(frac*pow(10,number_of_decimal_places));
}
#include <iostream>
#include <cmath>
double round(double r) {
return (r > 0.0) ? std::floor(r + 0.5) : std::ceil(r - 0.5);
}
double floor_to_zero(double f) {
return (f > 0.0) ? std::floor(f) : std::ceil(f);
}
double sign(double s) {
return (s < 0.0) ? -1.0 : 1.0;
}
int frac(double f, int prec) {
return round((f - floor_to_zero(f)) * prec) * sign(f);
}
int main() {
double a = 1.2345;
double b = -34.567;
std::cout << frac(a, 100) << " " << frac(b, 100) << std::endl; // 23 57
}
another solution
int precision= 100;
double number = 3.35;
int f = floor(xx);
double temp = ( f - number ) * -1;
int fractional_part = temp * precision;
IF you need it as a string, a quite easy C style solution would be (should work for variable number of decimal places):
double yourNumber = 0.35f;
char buffer[32];
snprintf(buffer, 32, "%g", yourNumber);
strtok(buffer, "."); // Here we would get the part before . , should still check
char* fraction = strtok(NULL, ".");
int fractionAsInt = atoi(fraction);
This example lacks error handling in case of a bad string and is not feasible if you just need a fixed number of decimal places, since the arithmetic approaches work better there.
Something like this should work:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
static int get_frac(double value, unsigned short precision)
{
return (int)((value - (long)value) * pow(10, precision));
}
static int get_frac_no_trailing_zeros(double value, unsigned short precision)
{
int v = get_frac(value, precision);
while (v % 10 == 0)
v /= 10;
return v;
}
int main(int argc, char *argv[])
{
double v;
v = 123.4564;
printf("%.4f = %d\n", v, get_frac(v, 2));
printf("%.4f = %d\n", v, get_frac(v, 4));
printf("%.4f = %d\n", v, get_frac(v, 6));
printf("%.4f = %d\n", v, get_frac_no_trailing_zeros(v, 6));
return EXIT_SUCCESS;
}
You may also want to either avoid calling pow by having a user supply a number in a power of 10 in a first place, or use a lookup table.
Using some stl magic, here is the sample code:
typedef std::pair<int, int> SplitFloat;
SplitFloat Split(float value, int precision)
{
// Get integer part.
float left = std::floor(value);
// Get decimal part.
float right = (value - left) * float(std::pow(10, precision));
return SplitFloat(left, right);
}
It can be improved, but is pretty straightforward.
I just did something close to what you are trying to do, though I'm still pretty new. None the less, maybe this will help someone in the future as I landed here looking for results for my problem.
The first step is making sure that the variable that contains 3.35 is a double, but that's probably obvious.
Next, create a variable that is only an integer and set it's value equal to the value of the double. It will then only contain the whole number.
Then subtract the whole number (int) from the double. You will be left with the fraction/decimal value. From there, just multiply by 100.
Beyond the 100ths decimal value, you would have to do a little more configuring obviously, but it should be fairly simple to do with an if statement. If the decimal value is greater than .99, multiply 1000 instead etc..
Here's how I would do it.
#include <sstream>
#include <string>
int main()
{
double d = yourDesiredNumber; //this is your number
std::ostringstream out;
out << setprecision(yourDesiredPrecision) << std::fixed
<< std::showpoint << d;
std::istringstream in(out.str());
std::string wholePart; //you won't need this.
int fractionalPart;
std::getline(in, wholePart, '.');
in >> fractionalPart;
//now fractionalPart contains your desired value.
}
I'm pretty sure that instead of two different istringstream and ostringstream objects you could have gotten away with just one stringstream object, but I am not sure about the details (never used that class) so I didn't use it in the example.