"Nearly divisible" - numbers

I want to check if a floating point value is "nearly" a multiple of 32. E.g. 64.1 is "nearly" divisible by 32, and so is 63.9.
Right now I'm doing this:
#define NEARLY_DIVISIBLE 0.1f
float offset = fmodf( val, 32.0f ) ;
if( offset < NEARLY_DIVISIBLE )
{
// its near from above
}
// if it was 63.9, then the remainder would be large, so add some then and check again
else if( fmodf( val + 2*NEARLY_DIVISIBLE, 32.0f ) < NEARLY_DIVISIBLE )
{
// its near from below
}
Got a better way to do this?

well, you could cut out the second fmodf by just subtracting 32 one more time to get the mod from below.
if( offset < NEARLY_DIVISIBLE )
{
// it's near from above
}
else if( offset-32.0f>-1*NEARLY_DIVISIBLE)
{
// it's near from below
}

In a standard-compliant C implementation, one would use the remainder function instead of fmod:
#define NEARLY_DIVISIBLE 0.1f
float offset = remainderf(val, 32.0f);
if (fabsf(offset) < NEARLY_DIVISIBLE) {
// Stuff
}
If one is on a non-compliant platform (MSVC++, for example), then remainder isn't available, sadly. I think that fastmultiplication's answer is quite reasonable in that case.

You mention that you have to test near-divisibility with 32. The following theory ought to hold true for near-divisibility testing against powers of two:
#define THRESHOLD 0.11
int nearly_divisible(float f) {
// printf(" %f\n", (a - (float)((long) a)));
register long l1, l2;
l1 = (long) (f + THRESHOLD);
l2 = (long) f;
return !(l1 & 31) && (l2 & 31 ? 1 : f - (float) l2 <= THRESHOLD);
}
What we're doing is coercing the float, and float + THRESHOLD to long.
f (long) f (long) (f + THRESHOLD)
63.9 63 64
64 64 64
64.1 64 64
Now we test if (long) f is divisible with 32. Just check the lower five bits, if they are all set to zero, the number is divisible by 32. This leads to a series of false positives: 64.2 to 64.8, when converted to long, are also 64, and would pass the first test. So, we check if the difference between their truncated form and f is less than or equal to THRESHOLD.
This, too, has a problem: f - (float) l2 <= THRESHOLD would hold true for 64 and 64.1, but not for 63.9. So, we add an exception for numbers less than 64 (which, when incremented by THRESHOLD and subsequently coerced to long -- note that the test under discussion has to be inclusive with the first test -- is divisible by 32), by specifying that the lower 5 bits are not zero. This will hold true for 63 (1000000 - 1 == 1 11111).
A combination of these three tests would indicate whether the number is divisible by 32 or not. I hope this is clear, please forgive my weird English.
I just tested the extensibility to other powers of three -- the following program prints numbers between 383.5 and 388.4 that are divisible by 128.
#include <stdio.h>
#define THRESHOLD 0.11
int main(void) {
int nearly_divisible(float);
int i;
float f = 383.5;
for (i=0; i<50; i++) {
printf("%6.1f %s\n", f, (nearly_divisible(f) ? "true" : "false"));
f += 0.1;
}
return 0;
}
int nearly_divisible(float f) {
// printf(" %f\n", (a - (float)((long) a)));
register long l1, l2;
l1 = (long) (f + THRESHOLD);
l2 = (long) f;
return !(l1 & 127) && (l2 & 127 ? 1 : f - (float) l2 <= THRESHOLD);
}
Seems to work well so far!

I think it's right:
bool nearlyDivisible(float num,float div){
float f = num % div;
if(f>div/2.0f){
f=f-div;
}
f=f>0?f:0.0f-f;
return f<0.1f;
}

For what I gather you want to detect if a number is nearly divisible by other, right?
I'd do something like this:
#define NEARLY_DIVISIBLE 0.1f
bool IsNearlyDivisible(float n1, float n2)
{
float remainder = (fmodf(n1, n2) / n2);
remainder = remainder < 0f ? -remainder : remainder;
remainder = remainder > 0.5f ? 1 - remainder : remainder;
return (remainder <= NEARLY_DIVISIBLE);
}

Why wouldn't you just divide by 32, then round and take the difference between the rounded number and the actual result?
Something like (forgive the untested/pseudo code, no time to lookup):
#define NEARLY_DIVISIBLE 0.1f
float result = val / 32.0f;
float nearest_int = nearbyintf(result);
float difference = abs(result - nearest_int);
if( difference < NEARLY_DIVISIBLE )
{
// It's nearly divisible
}
If you still wanted to do checks from above and below, you could remove the abs, and check to see if the difference is >0 or <0.

This is without uing the fmodf twice.
int main(void)
{
#define NEARLY_DIVISIBLE 0.1f
#define DIVISOR 32.0f
#define ARRAY_SIZE 4
double test_var1[ARRAY_SIZE] = {63.9,64.1,65,63.8};
int i = 54;
double rest;
for(i=0;i<ARRAY_SIZE;i++)
{
rest = fmod(test_var1[i] ,DIVISOR);
if(rest < NEARLY_DIVISIBLE)
{
printf("Number %f max %f larger than a factor of the divisor:%f\n",test_var1[i],NEARLY_DIVISIBLE,DIVISOR);
}
else if( -(rest-DIVISOR) < NEARLY_DIVISIBLE)
{
printf("Number %f max %f less than a factor of the divisor:%f\n",test_var1[i],NEARLY_DIVISIBLE,DIVISOR);
}
}
return 0;
}

Related

How to emulate *really simple* variable bit shifts with SSE?

I have two variable bit-shifting code fragments that I want to SSE-vectorize by some means:
1) a = 1 << b (where b = 0..7 exactly), i.e. 0/1/2/3/4/5/6/7 -> 1/2/4/8/16/32/64/128/256
2) a = 1 << (8 * b) (where b = 0..7 exactly), i.e. 0/1/2/3/4/5/6/7 -> 1/0x100/0x10000/etc
OK, I know that AMD's XOP VPSHLQ would do this, as would AVX2's VPSHLQ. But my challenge here is whether this can be achieved on 'normal' (i.e. up to SSE4.2) SSE.
So, is there some funky SSE-family opcode sequence that will achieve the effect of either of these code fragments? These only need yield the listed output values for the specific input values (0-7).
Update: here's my attempt at 1), based on Peter Cordes' suggestion of using the floating point exponent to do simple variable bitshifting:
#include <stdint.h>
typedef union
{
int32_t i;
float f;
} uSpec;
void do_pow2(uint64_t *in_array, uint64_t *out_array, int num_loops)
{
uSpec u;
for (int i=0; i<num_loops; i++)
{
int32_t x = *(int32_t *)&in_array[i];
u.i = (127 + x) << 23;
int32_t r = (int32_t) u.f;
out_array[i] = r;
}
}

Creating an online palindrome

I am trying to create an online palindrome sensor(The alphabet consists of 0,1,2,3,...9). The code is as follows:
#include<iostream>
#include<cmath>
using namespace std;
int main()
{
int x=0;
int y=0;
int c;
int i=0;
while(1)
{
cin>>c;
//I keep a track of previous number in x and its reverse in y and use them to create the
//the new number and reverse at every input. Then I compare x and y. If equal the number is
//a palindrome.
/*eg:(When 121 is entered digit by digit)
i=0:-
x=10*0+1 y=0+ 10^0 *1
i=1:-
x=10*1+2 y=1+ 10^1 *2
i=2:-
x=10*12+1 y=21+ 10^2 *1
*/
x=10*x+c;
y=y+ static_cast<int>(pow(10.0,static_cast<double>(i)) *c);
cout<<"y= "<<y<<" and "<<"x= "<<x<<endl;
if(y==x)
cout<<"Palindrome"<<endl;
i++;
}
return 0;
}
First, I enter 1 and it was indicated as palindrome(as expected). Then, I entered 2 and nothing happened(as expected, 'y= 21 and x= 12' was printed). But, then I again entered 1 and this time too nothing happened(not as expected) and this was printed:
y= 120 and x= 121
Can anyone tell me, how did y become 120 when it was supposed to be 121?
You are doing far too much math:
public static boolean isPalindrom(char[] word){
int i1 = 0;
int i2 = word.length - 1;
while (i2 > i1) {
if (word[i1] != word[i2]) {
return false;
}
++i1;
--i2;
}
return true;
}
All you need to do is fill an array with values as the user enters them and invoke a function similar to this. The use of exponents is a colossal waste of resources when simpler solutions exist.

Round to "beautiful" value

guys, I'm making simple graph drawer and want to find beautiful values for horizontal lines.
For example, if I have value equals to 72089.601562, beautiful is 70000, or 75000. So, I think that beautifulNumber%5 = 0.
Have you any ideas?
How about this?
#import <math.h>
#import <stdio.h>
#define ROUNDING 5000
int beautify(float input)
{
// Cast to int, losing the decimal value.
int value = (int)input;
value = (value / ROUNDING) * ROUNDING;
if ((int)input % ROUNDING > ROUNDING / 2 )
{
value += ROUNDING;
}
return value;
}
int main()
{
printf("%d\n", beautify(70000.601562)); // 70000
printf("%d\n", beautify(72089.601562)); // 70000
printf("%d\n", beautify(76089.601562)); // 75000
printf("%d\n", beautify(79089.601562)); // 80000
printf("%d\n", beautify(70000.601562)); // 70000
return 0;
}
It depends whether you want a floor value, a ceiling value or just to round to the nearest 5000.
For a floor value:
int beautiful = (int)(floor(ugly / 5000.0) * 5000.0);
For a ceiling value:
int beautiful = (int)(ceil(ugly / 5000.0) * 5000.0);
For rounding:
int beautiful = (int)(round(ugly / 5000.0) * 5000.0);
For making graph lines, I'd probably find the minimum and maximum values you have to graph, start with a floor value for the minimum value and then add your desired interval until you have surpassed your maximum value.
For instance:
float minValue = 2.34;
float maxValue = 7.72;
int interval = 1;
NSMutableArray *horizLines = [NSMutableArray array];
int line = (int)(floor(minValue / interval) * interval);
[horizLines addObject:[NSNumber numberWithInt:line]];
do {
line = (int)(ceil(minValue / interval) * interval);
[horizLines addObject:[NSNumber numberWithInt:line]];
if (minValue >= maxValue) break;
minValue = minValue + interval;
}
Use as needed!
Well, it seems like you'd want it to scale based on the size of the number. If the range only goes to 10, then obviously rounding to the nearest 5,000 doesn't make sense. There's probably a really elegant way to code it using bit shifting but just something like this will do the trick:
float value = 72089.601562
int beautiful = 0;
// EDIT to support returning a float for small numbers:
if (value < 0.2) beautiful = int(value*100)/100.;
else if (value < 2.) beautiful = int(value*10)/10.;
// Anything bigger is easy:
else if (value < 20) beautiful = (int)value;
else if (value < 200) beautiful = (int)value/10;
else if (value < 2000) beautiful = (int)value/100;
else if (value < 20000) beautiful = (int)value/1000;
// etc
Sounds like what you want to do is round to 1 or perhaps 2 significant digits. Rounding to n significant digits is pretty easy:
double roundToNDigits(double x, int n) {
double basis = pow(10.0, floor(log10(x)) - (n-1));
return basis * round(x / basis);
}
This will give you roundToNDigits(74518.7, 1) == 70000.0 and roundToNDigits(7628.54, 1) == 8000.00
If you want to round to 1 or 2 digits (only 2 where the second digit is 5), you want something like:
double roundSpecial(double x) {
double basis = pow(10.0, floor(log10(x))) / 2.0;
return basis * round(x / basis);
}

Split a integer into its separate digits

Say I have an integer, 9802, is there a way I can split that value in the four individual digits : 9, 8, 0 & 2 ?
Keep doing modulo-10 and divide-by-10:
int n; // from somewhere
while (n) { digit = n % 10; n /= 10; }
This spits out the digits from least-significant to most-significant. You can clearly generalise this to any number base.
You probably want to use mod and divide to get these digits.
Something like:
Grab first digit:
Parse digit: 9802 mod 10 = 2
Remove digit: (int)(9802 / 10) = 980
Grab second digit:
Parse digit: 980 mod 10 = 0
Remove digit: (int)(980 / 10) = 98
Something like that.
if you need to display the digits in the same order you will need to do the module twice visa verse this is the code doing that:
#import <Foundation/Foundation.h>
int main (int argc, char * argv[])
{
#autoreleasepool {
int number1, number2=0 , right_digit , count=0;
NSLog (#"Enter your number.");
scanf ("%i", &number);
do {
right_digit = number1 % 10;
number1 /= 10;
For(int i=0 ;i<count; i++)
{
right_digit = right_digit*10;
}
Number2+= right_digit;
Count++;
}
while ( number != 0 );
do {
right_digit = number2 % 10;
number2 /= 10;
Nslog(#”digit = %i”, number2);
}
while ( number != 0 );
}
}
return 0;
}
i hope that it is useful :)

Finding log2() using sqrt()

This is an interview question I saw on some site.
It was mentioned that the answer involves forming a recurrence of log2() as follows:
double log2(double x )
{
if ( x<=2 ) return 1;
if ( IsSqureNum(x) )
return log2(sqrt(x) ) * 2;
return log2( sqrt(x) ) * 2 + 1; // Why the plus one here.
}
as for the recurrence, clearly the +1 is wrong. Also, the base case is also erroneous.
Does anyone know a better answer?
How is log() and log10() actually implemented in C.
Perhaps I have found the exact answers the interviewers were looking for. From my part, I would say it's little bit difficult to derive this under interview pressure. The idea is, say you want to find log2(13), you can know that it lies between 3 to 4. Also 3 = log2(8) and 4 = log2(16),
from properties of logarithm, we know that log( sqrt( (8*16) ) = (log(8) + log(16))/2 = (3+4)/2 = 3.5
Now, sqrt(8*16) = 11.3137 and log2(11.3137) = 3.5. Since 11.3137<13, we know that our desired log2(13) would lie between 3.5 and 4 and we proceed to locate that. It is easy to notice that this has a Binary Search solution and we iterate up to a point when our value converges to the value whose log2() we wish to find. Code is given below:
double Log2(double val)
{
int lox,hix;
double rval, lval;
hix = 0;
while((1<<hix)<val)
hix++;
lox =hix-1;
lval = (1<<lox) ;
rval = (1<<hix);
double lo=lox,hi=hix;
// cout<<lox<<" "<<hix<<endl;
//cout<<lval<<" "<<rval;
while( fabs(lval-val)>1e-7)
{
double mid = (lo+hi)/2;
double midValue = sqrt(lval*rval);
if ( midValue > val)
{
hi = mid;
rval = midValue;
}
else{
lo=mid;
lval = midValue;
}
}
return lo;
}
It's been a long time since I've written pure C, so here it is in C++ (I think the only difference is the output function, so you should be able to follow it):
#include <iostream>
using namespace std;
const static double CUTOFF = 1e-10;
double log2_aux(double x, double power, double twoToTheMinusN, unsigned int accumulator) {
if (twoToTheMinusN < CUTOFF)
return accumulator * twoToTheMinusN * 2;
else {
int thisBit;
if (x > power) {
thisBit = 1;
x /= power;
}
else
thisBit = 0;
accumulator = (accumulator << 1) + thisBit;
return log2_aux(x, sqrt(power), twoToTheMinusN / 2.0, accumulator);
}
}
double mylog2(double x) {
if (x < 1)
return -mylog2(1.0/x);
else if (x == 1)
return 0;
else if (x > 2.0)
return mylog2(x / 2.0) + 1;
else
return log2_aux(x, 2.0, 1.0, 0);
}
int main() {
cout << "5 " << mylog2(5) << "\n";
cout << "1.25 " << mylog2(1.25) << "\n";
return 0;
}
The function 'mylog2' does some simple log trickery to get a related number which is between 1 and 2, then call log2_aux with that number.
The log2_aux more or less follows the algorithm that Scorpi0 linked to above. At each step, you get 1 bit of the result. When you have enough bits, stop.
If you can get a hold of a copy, the Feynman Lectures on Physics, number 23, starts off with a great explanation of logs and more or less how to do this conversion. Vastly superior to the Wikipedia article.