Knapsack with double data types - c++

For all the Knapsack problem that I've seen so far on the internet, all of them have the form (cost, value) given a capacity of the cost variable. All of the problems seems to have cost as an integer only which makes it quite convenient to make a 2D array for Value and Keep array. But what if the cost variable isn't an integer but instead a double data type? There's no way to make a Value and Keep array based on the double data type. How can I approach this situation?
Ex:
budget: $3458
item_name(laptop) cost(1177.44) value (131)
item_name(desktop) cost(1054.44) value(35)
item_name(GPU) cost(1252.66) value(105)
item_name(CPU) cost(946.021) value(136)

You can scan your input for the smallest exponent (using frexp()), and add in the mantissa precision (53 bits?) to find a scaling factor that will convert all your numbers to exactly proportionate integers.
You will need a bigint library to handle the resulting integers, though.

Switch to a dynamic program that finds the least costly solution for each value, with 2D arrays for Cost and Keep instead of Value and Keep. (The difference between the programs is minor.)

Related

How to parse the division of two very large numbers into a double?

I have a geometric algorithm which takes as input a polygon. However, the files I am supposed to use as input files store the coordinates of the polygons in a rather peculiar way. Each file consists of one line, a counterclockwise sequence of the vertices. Each vertex is represented by its x and y coordinates each of which is written as the quotient of two integers int/int. However, these integers are incredibly large. I wrote a program that parses them from a string into long long using the function std::stoll. However, it appears that some of the numbers in the input file are larger than 2^64.
The output coordinates are usually quite small, in the range 0-1000. How do I go about parsing these numbers and then dividing them, obtaining doubles? Is there any standard library way of doing this, or should I use something like the boost library?
If you are after a ratio of two large numbers as string, you can shorten the strings:
"194725681173571753193674" divided by "635482929374729202" is the same as
"1947256811735717" divided by "6354829293" to at least 9 digits (I just removed the same amount of digits on both sides). Depending on the needed precision, this might be the simplest solution. Just remove digits before converting to long long.
You can parse the inputs directly into a long double I believe. However, that approach will introduce precision errors. If precision is important, then avoid this.
A general solution for precise results is to represent the large integer with an array of integers where one integer represents the lower order bytes, next integer represents the larger bytes etc. This is generally called arbitrary precision arithmetic.
Is there any standard library way of doing this
No, other than basic building blocks such as vector for storing the array.
or should I use something like the boost library?
That's often a good place to start. Boost happens to have a library for this.

Ways around using a double as a key in a std set/map

The problem of using doubles as keys in maps/sets is floating point precision.
Some people have suggested adding an epsilon in your compare function, but that means your keys will no longer fulfil the necessary strict weak ordering criterion. This means that you will get a different set/map depending on the order of inserting your elements.
In the case where you want to aggregate/combine/merge data based on double values, and are willing to allow a certain level of rounding/epsilon (clearly, you'll have to), is the following solution a good idea?
Convert all the doubles (where we intended as keys) into integers by multiplying them by the precision factor (e.g. 1e8) and rounding to the nearest integer (int)i+0.5(if i>0), then create a set/map that keys off these integers. When extracting the final values of the keys, divide the ints by the precision factor to get the double value back (albeit rounded).
"Convert all the doubles (where we intended as keys) into integers by multiplying them by the precision factor (e.g. 1e8) and rounding to the nearest integer (int)i+0.5(if i>0), then create a set/map that keys off these integers. When extracting the final values of the keys, divide the ints by the precision factor to get the double value back (albeit rounded)."
I would recommend using integer type keys (e.g. long long) for the map in first place, and trim them for double representation using a fixed precision for division.
But that depends, if you are able to apply fix point math for your actual use case. If you need to cover a wide range of value precisions (like e.g. +-1e-7 - +-1e7), such approach won't work.
Convert all the doubles (where we intended as keys) into integers by
multiplying them by the precision factor (e.g. 1e8) and rounding to
the nearest integer (int)i+0.5(if i>0), then create a set/map that
keys off these integers. When extracting the final values of the keys,
divide the ints by the precision factor to get the double value back
(albeit rounded).
Instead of dividing by the precision factor to get the doubles back, simply store the double together with the associated value in a struct, and put that struct in the dictionary as the "value" for that integer key. That way, the original double value is still around and can be used for calculations. Just not for the key search.
If, however, you can live with slightly rounded values (due to the fact you simply divide an integer by an epsilon), your suggested approach is already good enough.
As the other answer says, it very much depends on the range of the values. If some are extremely huge and others are extremely small, then your approach to get integer keys won't work. If they are only a few digits apart, then it might.

How does Microsoft Calculator, calculate such large numbers?

I am up to about 8E10000 so how is it calculating such large number, there is no variable that can hold such large numbers.
Normal types in C can usually only store up to 64 bits, instead of a single variable, you can use an array of characters to store digits of your number and write functions for each operation (sum, minus and so on) in your program.
You may look at this: GNU Multiple Precision Arithmetic Library
In a nut shell they aren't using one variable to hold the operands but data structures than can probably hold arbitrary long numbers (like an array) and they evaluate operations by considering the number to be in a large radix system.
When you actually do a math operation the operands aren't variables but array (or any other data structure that is suitable) and you do it by doing the operation (where available) component wise.
When you want to add 2 array you choose a radix and then loop the arrays and add op1[i] to op2[i] then you take that value and check to see if it its bigger than your radix and compute a carriage that you add to next addition.
car = (op1[i] + op2[i])%radix
You need to be careful in choosing the radix and the underlaying data so an addition doesn't cause an overflow.
This how you also do when you add numbers in the base 10 by hand but without taking into account the radix.
You can also look over this for a bigint package.

Fastest way to add numbers in a very large arithmetic series?

I'm trying to minimize overhead as much as possible when adding numbers in an arithmetic series. I'm talking about a very large set, such as from 1 to 2^128. Is there any fast way of doing this? If so, what would it be without actually using the arithmetic sequence sum formula? Just as a reference, the sum from 1 to 2^128 is:
57896044618658097711785492504343953926464851149359812787997104700240680714240
Only fast way is to use the formula:
n * (n+1) / 2
Any other method (adding naively) will take way too long! (Even if you had a million years on a supercomputer, you wouldn't finish the calculation).
For such a large integer though, you cannot use normal integers. You will need to use a big integer object. So get a Big Integer library, eg. Google search, https://mattmccutchen.net/bigint/.
Note: a 256-bit integer may be able to hold results up to around that scale, but it is quite platform and compiler-dependent, as to whether 256-bit integers are readily available, and how they are used.

Is it possble to combine number of float values into one float value and extract the values when needed?

Am working on an algorithm for an iPhone app, where the data i need to keep in memory is exceeding the limit, so is it possible to represent number of float numbers as one float value and retrieve those value when i need.
For instance:
float array[4];
array[0]=0.12324;
array[1]=0.56732;
array[2]=0.86555;
array[3]=0.34545;
float combinedvalue=?
Not in general, no. You can't store 4N bits of information in only N bits.
If there's some patten in your numbers, then you might find a scheme. For example, if all your numbers are of similar value, you could potentially store only the differences between the numbers in lower precision.
However, this kind of thing is difficult, and limited.
If those numbers are exactly 5 digits each, you can treat them as ints by multiplying with 100000. Then you'll need 17 bits for each number, 68 bits in total, which (with some bit-shifting) takes up 9 bytes. Does that help, 9 bytes instead of 16?
Please note that the implementation of your algorithm will also take up memory!
What you are requiring could be accomplished in several different ways.
For instance, in c++ you generally have single precision floats (4 bytes) as the smallest precision available, though I wouldn't be surprised if there are other packages that handle smaller precision floating point values.
Therefore, if you are using double precision floating point values and can get by with less precision then you can switch to a smaller precision.
Now, depending on your range of values you want to store, you might be able to use a fixed-point representation as well, but you will need to be familiar with the nuances of bit shifting and masking, etc. But, another added benefit of this approach is that it could make your program run faster since fixed-point (integer) arithmetic is much faster than floating-point arithmetic.
The choice of options depends on your data you need to store and how comfortable you are with lower level binary arithmetic.