Calculating proportion with negative float values - c++

I'd like to know if there's any way in C++ to calculate a proportion involving possibily negative values in both vars and extremes.
My goal is to sync a float text input widget with fixed extremes ( eg the user can input any double value between A (min) and B (max) with A,B=any_constant_real_number ) with a slider who can only slide between 0 and 100 ( to simplify ).
If A and B are positive everything is trivial. as
val_slider = ((val_textin-A)*100)/(B-A)
but as A and B can be assumed real it looks to me the only possibility is to use several if/cases, or huge formulas involving a lot of abs() and checks over 0-divisions, whose are quite error prone and very cost intense compared to such an easy task.
Is there any faster and shorter way to achieve the same in c/c++/stl?
Pardon my bad english. Any hint? Thank you.

Your formula should work fine with negative values of A and B as well, as log as A < B.
Example, if you want the user to be able to enter values from -100 to 100, and map these to a slider which goes from 0 - 100, when the user enters -90 you get:
((-90 - A) * 100) / (B - A) = ((-90 - (-100)) * 100) / (100 - (-100))
= 10 * 100 / 200
= 5
An input value of 50 results in a slider value of:
((50 - A) * 100) / (B - A) = ((50 - (-100)) * 100) / (100 - (-100))
= 150 * 100 / 200
= 75

I don't know C++, but I do know Math, so try:
val_slider = 100 * ( val_textin - A ) / ( B - A )
Hey wait. That's exactly what you have. Test case..
A=-200, B=+200, val_texin = 100 (75% of bar, right?)
val_slider = 100 * ( 100 - -200 ) / ( 200 - - 200 )
= ( 300 ) / ( 400 ) * 100
= 75
See, you got it right. The only thing that COULD happen is B==A, but that can't be accounted for with math and requires a single IF. If they are equal, val_slider is exactly B (or A, as they are equal).

Related

How to divide a number into several, unequal, yet increasing numbers [ for sending a PlaceOrder( OP_BUY, lots ) contract XTO ]

I try to create an MQL4-script (an almost C++ related language, MQL4) where I want to divide a double value into 9 parts, where the fractions would be unequal, yet increasing
My current code attempts to do it this way (pseudo-code) :
Lots1 = 0.1;
Lots2 = (Lots1 / 100) * 120;//120% of Lot1
Lots3 = (Lots2 / 100) * 130;//130% of Lot2
Lots4 = (Lots3 / 100) * 140;//140% of Lot3
Lots5 = (Lots4 / 100) * 140;//140% of Lot4
Lots6 = (Lots5 / 100) * 160;//160% of Lot5
Lots7 = (Lots6 / 100) * 170;//170% of Lot6
Lots8 = (Lots7 / 100) * 180;//180% of Lot7
Lots9 = (Lots8 / 100) * 190;//190% of Lot8
...
or better :
double Lots = 0.1; // a Lot Size
double lot = Lots;
...
/* Here is the array with percentages of lots' increments
in order */
int AllZoneLots[8] = { 120, 130, 140, 140, 160, 170, 180, 190 }; // 120%, 130%,...
/* Here, the lot sizes are used by looping the array
and increasing the lot size by the count */
for( int i = 0; i < ArraySize( AllZoneLots ); i++ ) {
lots = AllZoneLots[i] * ( lots / 100 ) *;
// PlaceOrder( OP_BUY, lots );
}
But, what I want is to just have a fixed value of 6.7 split into 9 parts, like these codes do, yet to have the value increasing, rather than being same...
e.g, 6.7 split into :
double lots = { 0.10, 0.12, 0.16, 0.22, 0.31, 0.50, 0.85, 1.53, 2.91 };
/* This is just an example
of how to divide a value of 6.7 into 9, growing parts
This can be done so as to make equal steps in the values. If there are 9 steps, divide the value by 45 to get the first value, and the equal step x. Why? Because the sum of 1..9 is 45.
x = 6.7 / 45
which is 0.148889
The first term is x, the second term is 2 * x, the third term is 3 * x etc. They add up to 45 * x which is 6.7, but it's better to divide last. So the second term, say, would be 6.7 * 2 / 45;
Here is code which shows how it can be done in C, since MQL4 works with C Syntax:
#include <stdio.h>
int main(void) {
double val = 6.7;
double term;
double sum = 0;
for(int i = 1; i <= 9; i++) {
term = val * i / 45;
printf("%.3f ", term);
sum += term;
}
printf("\nsum = %.3f\n", sum);
}
Program output:
0.149 0.298 0.447 0.596 0.744 0.893 1.042 1.191 1.340
sum = 6.700
Not sure I understood right, but probably you need total of 3.5 shared between all lots.
And I can see only 8 lots not counting initial one.
totalPercentage = 0;
for(int i = 0; i < ArraySize(AllZoneLots); i++) {
totalPercentage += AllZoneLots[i];
}
double totalValue = 3.5;
// total value is total percentage, Lots1 - 100%, so:
Lots1 = totalValue / totalPercentage * 100.00;
Then you continue with your code.
If you want to include Lots1, you just add 100 to the total and do the same.
Q : How to divide a number into several, unequal, yet increasing numbers [ for sending a PlaceOrder( OP_BUY, lots ) contract XTO ]?
A : The problem is not as free as it might look for a first sight :
In metatrader Terminal ecosystem, the problem formulation has also to obey the externally decided factors ( that are mandatory for any XTO with an ambition not to get rejected, as being principally incompatible with the XTO Terms & Conditions set, and to get filled ~ "placed" At Market )
These factors are reportable via a call to:
MarketInfo( <_a_SymbolToReportSTRING>, MODE_MINLOT ); // a minimum permitted size
MarketInfo( <_a_SymbolToReportSTRING>, MODE_LOTSTEP ); // a mandatory size-stepping
MarketInfo( <_a_SymbolToReportSTRING>, MODE_MAXLOT ); // a maximum permitted size
Additionally, any such lot-size has to be prior of submitting an XTO also "normalised" for given number of decimal places, so as to successfully placed / accepted by the Trading-Server on the Broker's side. A failure to do so results in remotely rejected XTO-s ( which obviously come at a remarkable blocking / immense code-execution latency penalty one would always want to prevent from ever happening in real trading )
Last, but not least, any such XTO sizing has to be covered by a safe amount of leveraged equity ( checking the free-margin availability first, before ever sending any such XTO for reasons just mentioned above ).
The code:
While the initial pseudo-code above, does a progressive ( Martingale-alike ) lot-size scaling:
>>> aListOfFACTORs = [ 100, 120, 130, 140, 140, 160, 170, 180, 190 ]
>>> for endPoint in range( len( aListOfFACTORs ) ):
... product = 1.
... for item in aListOfFACTORs[:1+endPoint]:
... product *= item / 100.
... print( "Lots{0:} ~ ought be about {1:} times the amount of Lots1".format( 1 + endPoint, product ) )
...
Lots1 ~ ought be about 1.0 times the amount of Lots1
Lots2 ~ ought be about 1.2 times the amount of Lots1
Lots3 ~ ought be about 1.56 times the amount of Lots1
Lots4 ~ ought be about 2.184 times the amount of Lots1
Lots5 ~ ought be about 3.0576 times the amount of Lots1
Lots6 ~ ought be about 4.89216 times the amount of Lots1
Lots7 ~ ought be about 8.316672 times the amount of Lots1
Lots8 ~ ought be about 14.9700096 times the amount of Lots1
Lots9 ~ ought be about 28.44301824 times the amount of Lots1
the _MINLOT, _LOTSTEP and _MAXLOT put the game into a new light.
Any successful strategy is not free to chose the sizes. Given the said 9-steps and a fixed amount of the total-amount ~ 6.7 lots, the process can obey the stepping and total, plus, it must obey the MarketInfo()-reported sizing algebra
Given 9-steps are mandatory,
each one has to be at least _MINLOT-sized:
double total_amount_to_split = aSizeToSPLIT;
total_amount_to_split = Min( aSizeToSPLIT, // a wished-to-have-sizing
FreeMargin/LotInBaseCurr*sFty // a FreeMargin-covered size
);
int next = 0;
while ( total_amount_to_split >= _MINLOT )
{ total_amount_to_split -= _MINLOT;
lot_size[next++] = _MINLOT;
}
/*
###################################################################################
------------------------------------------------- HERE, WE HAVE 0:next lot_sizes
next NEED NOT == 9
If there is anything yet to split:
there is an integer amount of _LOTSTEP-s to distribute among 'em
HERE, and ONLY here, you have a freedom to decide about split/mapping
of the integer amount of _LOTSTEP-sized
additions to the _MINLOT "pre"-sets
in lot_size[]-s
YET, still no more than _MAXLOT is permissible for the above explained reasons
------------------------------------------------- CODE has to obey this, if XTO-s
are to
get a chance
###################################################################################
*/

Unit testing Datetime values

I have a function that makes use of the current time (now). The Contract as a whole is a Crowdfunding token and the cost of tokens differ depending on the date and time that tokens are purchased.
How does one simulate different times when testing a Smart Contract? For instance, with regards to the code below, I would like to do unit testing to find out if the code for setting price is correct but I can't change the value of now.
Would it be a good solution to simply substitute the now keyword for another temporary testing variable, say now_sim and then manually changing now_sim during simulation?
if (now < (startTime + 1 days)) {
currentPrice = safeDiv(safeMul(price, 80), 100); // 20 % discount (x * 80 / 100)
}
else if (now < (startTime + 2 days)) {
currentPrice = safeDiv(safeMul(price, 90), 100); // 10 % discount (x * 90 / 100)
}
else if (now < (startTime + 12 days)) {
// 1 % reduction in the discounted rate from day 2 until day 12 (sliding scale per second)
// 8640000 is 60 x 60 x 24 x 100 (100 for 1%) (60 x 60 x 24 for seconds per day)
currentPrice = price - safeDiv(safeMul((startTime + 12 days) - now), price), 8640000);
}
else {
currentPrice = price;
}
If you use pyethereum for testing - which I highly recommend, it's lovely - you can directly alter the timestamp of the simulated block that is mining your transaction.
self.s = t.state()
self.s.block.timestamp = self.s.block.timestamp + 86400
self.s.mine(1)
some_val = your_contract.do_something(some_parameter)
self.assertEqual(some_val, whatever)
See a working example here (maybe a bit out-of-date): https://github.com/realitykeys/subjectivocracy/blob/master/contracts/test.py#L85

Convert decibel range to byte range

Greeting,
I'm trying to find a formula to convert a range where:
min = -100db and max = -30db
to:
min = 0 and max = 255
for example: -60db = ?
Seems easy but it makes my head spin.
Assuming you mean the result to stay in terms of db, you're asking for a simple linear interpolation:
f(x) = ymin + (x - xmin)*(ymax - ymin)/(xmax - xmin)
or in your case,
f(x) = 0 + (x + 100)*(255 - 0)/(-30 + 100)
f(-60 db) = 145.714
If instead you're talking about converting db to a scale factor with which to multiply an audio signal, then it's a bit more complex. For example, to multiply an audio signal by 0 is negative infinity db. So (at the very least) you'd have to special case that.

Make very small, (or large), exponential calculations

Exponential limit of most 32 bit machines is
exp( +/-700 )
But I would like to do an exponential calculation
res = exp( x ) / exp( d )
when x or d are bigger than 700 I use the fact that
exp( x + y ) = exp( x ) . exp( y )
So my calculation would be something along the line of
res = (exp( x - z ).exp(z)) / (exp( d - z ).exp(z))
or
res = exp( x - z ) / exp( d - z )
where (x-z) < 700
But this approach is flawed in some cases, for example where x = 6000 and d = 10000
If we use z=5300 then
res = exp( 6000 - 5300 ) / exp( 10000 - 5300 )
res = exp( 700 ) / exp( 47000 )
But exp( 47000 ) = 0 on a 32 bit machine.
If I replace z = 9300 then I get the opposite effect.
res = exp( -3300 ) / exp( 700 )
So how could I solve the above equations, (that should return a 32bit valid number I think), given the limitations of the computer?
Edit
The reason for doing this is I am using the formula
P( a ) = P(y1) * P(y2) * P(y3) ... P(yN)
In order to prevent overflow I then do
a = log( P(y1) ) + log( P(y2) ) + log (P(y3)) ... log( P(yN) )
b = log( P(z1) ) + log( P(z2) ) + log (P(z3)) ... log( P(zN) )
...
z = log( P(zz1) ) + log( P(zz2) ) + log (P(zz3)) ... log( P(zzN) )
to get a total I do
total = a + b ... z
and to calculate the percentage I do
(exp(a) / exp( total ) ) * 100
but it is possible that "a" and/or "total" are greater than 700
I guess the question could be how could I calculate the percentage without using the exponential
It doesn't matter that the answer should be a 32 bit number if some of the intermediate steps in the calculations aren't.
For math that goes outside the bounds of an int or long type, you probably need to start using something like GMP.
https://gmplib.org/
I assume that you want to compute this:
p = exp(a) / exp(b)
And since a^b/a^c == a^(b-c) this reduces to
p = exp(a - b)
which can be easily computed if that difference is below that critical exponent.
If it isn't, then your result cannot be represented by primitive datatypes like double (because it's either extremely large or extremely small), you then need some kind of arbitrary precision numbers, probably provided by some library.
But if you only need to print the result, or store it somehow, then you can easily compute even extremely large numbers:
For that, you change to base 10 (for displaying), compute the equivalent exponent therefore (tExponent = log10(eExponent)), and get that value into the allowed range between std::numeric_limits::max_exponent10 and std::numeric_limits::min_exponent10, saving the difference as scaling factor.
For now, I just have a quick and dirty live example, showing
exp(90000) / exp(100) = 1.18556 scaled by 10^39043
(Check at wolfram alpha)
Note: When I wrote this, it was pretty late in the evening. I'm leaving this here for an "alternative" approach.
Now, generally, there's
a^b = [a^(b/c)]^c
And since
(a/b)^c = (a^c)/(b^c)
holds, too, I guess the easiest approach here is to just divide both exponents as long as one of them is above your critical value, then do the exponentiation, divide the results, and finally use the divisor of the former exponents as exponent for the quotient:
double large_exp_quot(
double eNum,
double eDenom,
unsigned int const critical = 200) {
if (abs(eNum - eDenom) > critical) {
throw out_of_range{"That won't work, resulting exponent is too large"};
}
unsigned int eDivisor = 1;
while (abs(eNum) > critical or abs(eDenom) > critical) {
eNum /= 2;
eDenom /= 2;
eDivisor *= 2;
}
return pow(exp(eNum) / exp(eDenom), eDivisor);
}
But this will only work, if the result of your computation can actually be stored using the C++ primitive datatypes, in this case double. The example you gave ... with exponents 6000 and 10000 ... is obviously not representable with a double (it's e^(-4000) and thus incredibly small)
Numerically unstable computation: exp(a) / exp(b)
Equivalent stable computation: exp(a - b)
Numerically unstable computation: Πi=1..n pi
Equivalent stable computation: exp(Σi=1..n log(pi))

C++ Weird Variable Issues

I'm using the following code to calculate and display the final score for a math game in C++.
int score = (correctNumber / 3) * 100;
cout << score;
The variable "correctNumber" is always a value between 0 and 3. However, unless "correctNumber" = 3, then the variable "score" always equals "0". When "correctNumber" equals 3 then "score" equals 100.
Say "correctNumber" was equal to 2. Shouldn't "score" be 67 then? Is this some issue with int variable type being unable to calculate decimal points?
You are doing math as integer so 1 / 3 is 0.
Try:
int score = (100 * correctNumber) / 3
and if you want to round:
int score = (100 * correctNumber + 1) / 3
I'm assuming correctNumber is an int, based on what you described. What's happening is integer truncation. When you divide an int by an int, the result always rounds down:
1/3 = 0.3333 = 0 as an integer
2/3 = 0.6667 = 0 as an integer
3/3 = 1.0000 = 1 as an integer
The easy way to remedy this here is to multiply it first:
int score = correctNumber * 100 / 3;
However, this still leaves you with 66 for 2, not 67. A clear and simple way of dealing with that (and many other rounding situations, though the rounding style is unconfigurable) is std::round, included since C++11:
int score = std::round(currentNumber * 100. / 3);
In the example, the dot in 100. makes 100 a double (it's the same thing as 100.0), so the result of the operation will be the floating-point value you want, not a pre-truncated value passed in as a floating-point value. That means you'll end up with 66.66666... going into std::round instead of 66.
Your guess is correct. int can't store real numbers.
But you can multiply first, and then divide, like
score = correctNumber * 100 / 3;
score will have 0, 33, 66, 100, depending on values of correctNumber
The problem is that (correctNumber / 3) is an integer, so you can't get 0.666 or any fraction to multiply by 100, which what I believe is you want.
You could try to force it to be a float like this:
int score = ((float)correctNumber / 3) * 100;
This, however, will give you 66 instead of 67, cause it doesn't round up. You could use C99 round() for that.
int score = round(((float)correctNumber / 3) * 100);
UPDATE:
You can also use + 0.5 to round, like this:
int score = (correctNumber / 3.0f) * 100.0f + 0.5f;