Solidity percentage calculation with variables vs literals gives different answers - solidity

contract test {
function calculatePrice(uint a, uint b) public pure returns (uint) {
return (a * (b / 100));
}
function calculatePrice2() public pure returns (uint) {
return (80 * (60 / 100));
}
}
So, the above two functions even though completely same give different answers.
for the first function if you pass a=80 and b=60 answer is zero but if you call the second function the answer is 48.
Why? the code is exactly the same except the first function is dynamic

The first function calculates with unsigned integers, meaning there are no decimals.
It first calculates 60 / 100, which results in 0 (integer, no decimals). And then calculates 80 * 0, which is still 0.
The second function takes the intermediate result as the fixed point number type.
It first calculates 60 / 100, resulting in 0.6 (fixed point number, not integer). And then calculates 80 * 0.6, resulting in 48.

Related

Converting a BigInteger to a string in some base: speed issue (Kotlin)

I want to convert large positive BigIntegers (up to many thousands of digits) to strings in Kotlin, using number bases up to 100 (and possibly higher).
For bases ≤36, there is of course toString(base), but for larger bases, I wrote this extension function:
fun BigInteger.toStringX(base: Int): String {
if (base <= 36) return toString(base) // improve speed if base <= 36
val bigBase = base.toBigInteger()
var n = this
val stringBuilder = StringBuilder()
while (n > ZERO) {
val div = n.divideAndRemainder(bigBase)
stringBuilder.append(DIGITS[div[1].toInt()])
n = div[0]
}
return stringBuilder.reverse().toString()
}
where DIGITS is a string containing the list of digits.
Now the native toString is faster by about an order of magnitude than my function – e.g. 60 ms for about 10,000 digits vs. 500 ms. Why is my function so slow? Any help improving on its speed (while maintinaing the ability to convert to bases > 36) would be appreciated.
(By the way, replacing append() with insert() and losing reverse() in the last line doesn't change much.)
Looking at the source code for the built-in toString, it seems to call this private toString, which implements a divide-and-conquer algorithm.
/**
* Converts the specified BigInteger to a string and appends to
* {#code sb}. This implements the recursive Schoenhage algorithm
* for base conversions. This method can only be called for non-negative
* numbers.
* <p>
* See Knuth, Donald, _The Art of Computer Programming_, Vol. 2,
* Answers to Exercises (4.4) Question 14.
*
* #param u The number to convert to a string.
* #param sb The StringBuilder that will be appended to in place.
* #param radix The base to convert to.
* #param digits The minimum number of digits to pad to.
*/
private static void toString(BigInteger u, StringBuilder sb,
int radix, int digits) {
...
results = u.divideAndRemainder(v);
int expectedDigits = 1 << n;
// Now recursively build the two halves of each number.
toString(results[0], sb, radix, digits - expectedDigits);
toString(results[1], sb, radix, expectedDigits);
}
This means that there is only O(log(N)) divisions, for an N-bit number. Compare this to your algorithm, which does O(N) divisions.
So for large numbers, you can implement this algorithm too - "split" the number up into smaller ones, then use your O(N) algorithm when they are small enough, all the while passing the string builder along, so the digits are appended.

How would i separate an answer in Kotlin do print 2 different types

Hi this is my first ever program I'm tryin to write in android studio/Kotlin and I'm not sure how to proceed.
so in my program i have a few math tasks to do and it does it fine but what I need to do now is separate part of the answer then covert it then print out both parts
for example if my answer was 1.5232 i would like to convert the decimal part of the answer to a string that matches a range if its in it. the ranges I have are in the .0000 area so I would like to limit the decimal range too.
so final result would look like this
1 (whatever my string in range is)
I hope I included enough info thank you in advance.
The first part of the task is to split the number into the integer and fractional components:
val input = 1.5232
val integer = input.toInt() // rounds DOWN to nearest smaller Int
val fractional = input % 1.0 // The remainder when dividing by 1.0 is the fraction
The strategy I would use to round to the nearest fractional value given a certain precision is to multiply by that precision, and round to the nearest integer. That would give you the numerator, and the precision would be the denominator:
val denominator = 8 // fractional precision
val numerator = (fractional * denominator).roundToInt() // rounds up or down to nearest Int
Then to put it together, you can use a string template:
val result = "$integer $numerator/$denominator"
println(result)
Simplifying the fraction would be another task if you need that. You can find various algorithms for finding greatest common divisor of two numbers. Use one of those and divide the numerator and denominator by that value.

'while' Loop in Objective-C

The following program calculates and removes the remainder of a number, adds the total of the remainders calculated and displays them.
#import <Foundation/Foundation.h>
int main (int argc, char * argv[]) {
#autoreleasepool {
int number, remainder, total;
NSLog(#"Enter your number");
scanf("%i", &number);
while (number != 0)
{
remainder = number % 10;
total += remainder;
number /= 10;
}
NSLog(#"%i", total);
}
return 0;
}
My questions are:
Why is the program set to continue as long as the number is not equal to 0? Shouldn't it continue as the long as the remainder is not equal to 0?
At what point is the remainder discarded from the value of number? Why is there no number -= remainder statement before n /=10?
[Bonus question: Does Objective-C get any easier to understand?]
The reason we continue until number != 0 instead of using remainder is that if our input is divisible by 10 exactly, then we don't get the proper output (the sum of the base 10 digits).
The remainder is dropped off because of integer division. Remember, an integer cannot hold a decimal place, so when we divide 16 by 10, we don't get 1.6, we just get 1.
And yes, Objective-C does get easier over time (but, as a side-note, this uses absolutely 0 features of Objective-C, so it's basically C with a NSLog call).
Note that the output isn't quite what you would expect at all times, however, as in C / ObjC, a (unlike languages like D or JS) a variable is not always initialized to a set value (in this case, you assume 0). This could cause UB down the road.
It checks to see if number is not equal to zero because remainder very well may never become zero. If we were to input 5 as our input value, the first time through the loop remainder would be set to 5 (because 5 % 10 = 5), and number would go to zero because
5 / 10 = 0.5, and ints do not store floating point values, so the .5 will get truncated and the value of number will equal zero.
The remainder does not get removed from the value of number in this code. I think that you may be confused about what the modulo operator does (see this explanation).
Bonus answer: learning a programming language is difficult at first, but very rewarding in the long run (if you stick with it). Each new language that you learn after your first will most likely be easier to learn too, because you will understand general programming constructs and practices. The best of luck on your endeavor!

Returning a number less than 1

I am working on an app that needs to utilize a ratio of a given number and multiply that ratio times another number. Problem is that I can't get numbers less that 1 to give me the proper decimal ratio, instead it gives me zero (when it should be .5).
Example:
float number = 1/2; // This gives me zero
double number = 1/2; // This also gives me zero
If you don't specify decimal places you're using integers which means the calculation is performed with integer precision before the result is cast to the type on the LHS. You want to do the the following when using hard coded numbers in your code:
float number = 1.0f / 2.0f;
double number = 1.0 / 2.0;
If you're aiming to use integer variables for an operation, you'll want to cast them to the type that you want for your result.
Try this
float number = 1.0/2.0;
Remember that 1 is an int, so you are essentially taking
(int)1 / (int)2
which returns
(int)0
To cast variables that are ints, do
float number = (float)numerator / (float)denominator;

Objective-C: Strange calculation result

I am learning Objective-C and have completed a simple program and got an unexpected result. This program is just a multiplication table test... User inputs the number of iterations(test questions), then inputs answers. That after program displays the number of right and wrong answers, percentage and accepted/failed result.
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSLog(#"Welcome to multiplication table test");
int rightAnswers; //the sum of the right answers
int wrongAnswers; //the sum of wrong answers
int combinations; //the number of combinations#
NSLog(#"Please, input the number of test combinations");
scanf("%d",&combinations);
for(int i=0; i<combinations; ++i)
{
int firstInt=rand()%8+1;
int secondInt=rand()%8+1;
int result=firstInt*secondInt;
int answer;
NSLog(#"%d*%d=",firstInt,secondInt);
scanf("%d",&answer);
if(answer==result)
{
NSLog(#"Ok");
rightAnswers++;
}
else
{
NSLog(#"Error");
wrongAnswers++;
}
}
int percent=(100/combinations)*rightAnswers;
NSLog(#"Combinations passed: %d",combinations);
NSLog(#"Answered right: %d times",rightAnswers);
NSLog(#"Answered wrong: %d times",wrongAnswers);
NSLog(#"Completed %d percent",percent);
if(percent>=70)NSLog(#"accepted");
else
NSLog(#"failed");
[pool drain];
return 0;
}
Problem (strange result)
When I input 3 iterations and answer 'em right, i am not getting of 100% right. Getting only
99%. The same count I tried on my iPhone calculator.
100 / 3 = 33.3333333... percentage for one right answer (program displays 33%. The digits after mantissa getting cut off)
33.3333333... * 3=100%
Can someone explain me where I went wrong? Thanx.
This is a result of integer division. When you perform division between two integer types, the result is automatically rounded towards 0 to form an integer. So, integer division of (100 / 3) gives a result of 33, not 33.33.... When you multiply that by 3, you get 99. To fix this, you can force floating point division by changing 100 to 100.0. The .0 tells the compiler that it should use a floating point type instead of an integer, forcing floating point division. As a result, rounding will not occur after the division. However, 33.33... cannot be represented exactly by binary numbers. Because of this, you may still see incorrect results at times. Since you store the result as an integer, rounding down will still occur after the multiplication, which will make it more obvious. If you want to use an integer type, you should use the round function on the result:
int percent = round((100.0 / combinations) * rightAnswers);
This will cause the number to be rounded to the closest integer before converting it to an integer type. Alternately, you could use a floating point storage type and specify a certain number of decimal places to display:
float percent = (100.0 / combinations) * rightAnswers;
NSLog(#"Completed %.1f percent",percent); // Display result with 1 decimal place
Finally, since floating point math will still cause rounding for numbers that can't be represented in binary, I would suggest multiplying by rightAnswers before dividing by combinations. This will increase the chances that the result is representable. For example, 100/3=33.33... is not representable and will be rounded. If you multiply by 3 first, you get 300/3=100, which is representable and will not be rounded.
Ints are integers. They can't represent an arbitrary real number like 1/3. Even floating-point numbers, which can represent reals, won't have enough precision to represent an infinitely repeating decimal like 100/3. You'll either need to use an arbitrary-precision library, use a library that includes rationals as a data type, or just store as much precision as you need and round from there (e.g. make your integer unit hundredths-of-a-percent instead of a single percentage point).
You might want to implement some sort of rounding because 33.333....*3 = 99.99999%. 3/10 is an infinite decimal therefore you need some sort of rounding to occur (maybe at the 3rd decimal place) so that the answer comes out correct. I would say if (num*1000 % 10 >= 5) num += .01 or something along those lines multiply by 100 moves decimal 3 times and then mod returns the 3rd digit (could be zero). You also might only want to round at the end once you sum everything up to avoid errors.
EDIT: Didn't realize you were using integers numbers at the end threw me off, you might want to use double or float (floats are slightly inaccurate past 2 or 3 digits which is OK with what you want).
100/3 is 33. Integer mathematics here.