Round to "beautiful" value - iphone

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);
}

Related

How do I round only millions in flutter?

The rule is if value >= 500,000 it will be rounded up to 1,000,000, if the value < 500,000 it will be rounded down to 000,000
Here an example, if I have value like 4,843,820,00 it will be rounded up to 4,844,000,000
If I have value like 1,136,362,500 it will be rounded down to 1,136,000,000
If I have value like 1,500,000 will be rounded up to 2,000,000 & if I have like 1,450,000 it will be rounded down to 1,000,000
Here is what I tried
String kmbGenerator(number) {
if (number > 999 && number < 99999) {
int resulta = (number / 1000).round();
return "$resulta,000";
} else if (number > 99999 && number < 999999) {
int resulta = (number / 1000).round();
return '${resulta.toStringAsFixed(0)},000';
} else if (number > 999999 && number < 999999999) {
int resulta = (number / 1000000).round();
return "$resulta,000,000";
} else if (number > 999999999) {
int resulta = (number / 1000000000).round();
return "$resulta,000,000,000";
} else {
return number.toString();
}
}
Divide by one million, round, then multiply by one million:
int roundMillions(int value) {
return (value / 1e6).round() * 1000000;
}
main() {
void test(int value) {
print('rounded $value to ${roundMillions(value)}');
}
test(4843820000);
test(1136362500);
test(1500000);
test(1450000);
}
Output:
rounded 4843820000 to 4844000000
rounded 1136362500 to 1136000000
rounded 1500000 to 2000000
rounded 1450000 to 1000000
Before you format round it using num.round() for example if you want to round to millions :
double n = 29971800;
double roundTo = 1000000; //million
print((n/roundTo).round()); //prints 30
you can either multiply it by million and format it or just convert to String and add ',000,000'

Calculate IRR (Internal Rate Return) and NPV programmatically in Objective-C

I am developing a financial app and require IRR (in-built functionality of Excel) calculation and found such great tutorials in C here and such answer in C# here.
I implemented code of the C language above, but it gives a perfect result when IRR is in positive. It is not returning a negative value when it should be. Whereas in Excel =IRR(values,guessrate) returns negative IRR as well for some values.
I have referred to code in above C# link too, and it seems that it follows good procedures and returns errors and also hope that it returns negative IRR too, the same as Excel. But I am not familiar with C#, so I am not able to implement the same code in Objective-C or C.
I am writing C code from the above link which I have implemented for helping you guys.
#define LOW_RATE 0.01
#define HIGH_RATE 0.5
#define MAX_ITERATION 1000
#define PRECISION_REQ 0.00000001
double computeIRR(double cf[], int numOfFlows)
{
int i = 0, j = 0;
double m = 0.0;
double old = 0.00;
double new = 0.00;
double oldguessRate = LOW_RATE;
double newguessRate = LOW_RATE;
double guessRate = LOW_RATE;
double lowGuessRate = LOW_RATE;
double highGuessRate = HIGH_RATE;
double npv = 0.0;
double denom = 0.0;
for (i=0; i<MAX_ITERATION; i++)
{
npv = 0.00;
for (j=0; j<numOfFlows; j++)
{
denom = pow((1 + guessRate),j);
npv = npv + (cf[j]/denom);
}
/* Stop checking once the required precision is achieved */
if ((npv > 0) && (npv < PRECISION_REQ))
break;
if (old == 0)
old = npv;
else
old = new;
new = npv;
if (i > 0)
{
if (old < new)
{
if (old < 0 && new < 0)
highGuessRate = newguessRate;
else
lowGuessRate = newguessRate;
}
else
{
if (old > 0 && new > 0)
lowGuessRate = newguessRate;
else
highGuessRate = newguessRate;
}
}
oldguessRate = guessRate;
guessRate = (lowGuessRate + highGuessRate) / 2;
newguessRate = guessRate;
}
return guessRate;
}
I have attached the result for some value which are different in Excel and the above C language code.
Values: Output of Excel: -33.5%
1 = -18.5, Output of C code: 0.010 or say (1.0%)
2 = -18.5,
3 = -18.5,
4 = -18.5,
5 = -18.5,
6 = 32.0
Guess rate: 0.1
Since low_rate and high_rate are both positive, you're not able to get a negative score. You have to change:
#define LOW_RATE 0.01
to, for example,
#define LOW_RATE -0.5

Return zero or positive number?

I was initially thinking that the code below would return 0, my question, is there a function that I can use to only receive zero/positive results here?
NSUInteger pruneSize = 5 - 20; // Returns: -15
Currently I am just checking the result myself, but was wondering if I was missing something simpler.
NSUInteger pruneSize = 5 - 20;
if(pruneSize >= 0) {
// Do zero/positive Stuff ...
}
pruneSize >= 0 is always true as pruneSize is unsigned. You should get a warning here. You need to change the type to NSInteger, that is the signed integer. If you want to clip the lower value to zero for a signed int then you can do this:
NSInteger pruneSize = 5 - 20; // signed int
pruneSize = pruneSize < 0 ? 0 : pruneSize;
You can use abs(pruneSize) which will return you positive or zero number in any case.
EDIT:
NSUInteger pruneSize = 5-20;
if(pruneSize < 0)
{
pruneSize = 0;
}
NSLog(#"%d",pruneSize);
Hope this helps you.
If you want your function to return always zero if your result is in negative(less than 0) then return zero or else return result
int n=0;
if(result > 0){ //positive
n = result
else
n = 0
return n
or use the abs method

floor double by decimal place

i want to floor a double by its decimal place with variable decimal length (in iphone sdk).
here some examples to show you what i mean
NSLog(#"%f",[self floorMyNumber:34.52462 toPlace:2); // should return 34.52
NSLog(#"%f",[self floorMyNumber:34.52662 toPlace:2); // should return 34.52
NSLog(#"%f",[self floorMyNumber:34.52432 toPlace:3); // should return 34.524
NSLog(#"%f",[self floorMyNumber:34.52462 toPlace:3); // should return 34.524
NSLog(#"%f",[self floorMyNumber:34.12462 toPlace:0); // should return 34.0
NSLog(#"%f",[self floorMyNumber:34.92462 toPlace:0); // should return 34.0
any ideas how to do this?
solution
-(double)floorNumberByDecimalPlace:(float)number place:(int)place {
return (double)((unsigned int)(number * (double)pow(10.0,(double)place))) / (double)pow(10.0,(double)place);
}
Another solution:
placed is 10 (Example: 13.1), 100 (Example: 12.31) and so on
double value = (double)((unsigned int)(value * (double)placed)) / (double)placed
If you're just rounding them for the purpose of printing them, you do this with the standard printf format specifiers. For example, instead of "%f", to print 3 decimals you could use "%.3f"
Use sprintf (or better snprintf) to format it to a string then crop the end of the string.
Multiply it by 10^(decimal places), cast it to an integer, then divide it by 10^(decimal places).
double floorToPlace(double number, int places)
{
int decimalPlaces = 1;
for (int i = 0; i < places; i++) divideBy *= 10;
return (int)(number * decimalPlaces) / (double)decimalPlaces;
}

"Nearly divisible"

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;
}