First, take a specific float f:
f = [64.4, 73.60, 77.90, 87.40, 95.40].sample # take any one of these special Floats
f.to_d.class == (1.to_d * f).class # => true (BigDecimal)
So multiplying by BigDecimal casts f to BigDecimal. Therefore 1.to_d * f (or f * 1.to_d) can be seen as a (poor, but still) form of converting f to BigDecimal. And yet for these specific values we have:
f.to_d == 1.to_d * f # => false (?!)
Isn't this a bug? I'd assume that while multiplying by 1.to_d Ruby should invoke f.to_d internally. But the results differ, i.e. for f = 64.4:
f.to_d # => #<BigDecimal:7f8202038280,'0.644E2',18(36)>
1.to_d * f # => #<BigDecimal:7f82019c1208,'0.6440000000 000001E2',27(45)>
I cannot see why floating-point representation error should be an excuse here, yet it's obviously a cause, somehow. So why is this happening?
PS. I wrote a snippet of code playing around with this issue:
https://github.com/Swarzkopf314/ruby_wtf/blob/master/multiplication_by_unit.rb
So why is this happening?
TL;DR different precisions are used.
Long answer:
64.4.to_d calls bigdecimal/util's Float#to_d:
def to_d(precision=nil)
BigDecimal(self, precision || Float::DIG)
end
Unless specified, it uses an implicit precision of Float::DIG which is 15 for current implementations:
Float::DIG
#=> 15
So 64.4.to_d is equivalent to:
BigDecimal(64.4, Float::DIG)
#=> #<BigDecimal:7fd7cc0aa838,'0.644E2',18(36)>
BigDecimal#* on the other hand converts a given float argument via:
if (RB_TYPE_P(r, T_FLOAT)) {
b = GetVpValueWithPrec(r, DBL_DIG+1, 1);
}
DBL_DIG is the C-equivalent of Float::DIG, so it's basically:
BigDecimal(64.4, Float::DIG + 1)
#=> #<BigDecimal:7fd7cc098408,'0.6440000000 000001E2',27(36)>
That said, you can get the expected result if you provide the precision explicitly, either:
f.to_d(16) == 1.to_d * f
#=> true
or:
f.to_d == 1.to_d.mult(f, 15)
#=> true
and of course by explicitly converting f via to_d:
f.to_d == 1.to_d * f.to_d
#=> true
Isn't this a bug?
It looks like one, you should file a bug report.
Note that neither 0.644E2, nor 0.6440000000000001E2 is an exact representation of the given floating point number. As already noted by Eli Sadoff, 64.4's exact value is 64.400000000000005684341886080801486968994140625, so the most exact BigDecimal representation would be:
BigDecimal('64.400000000000005684341886080801486968994140625')
#=> #<BigDecimal:7fd7cc04a0c8,'0.6440000000 0000005684 3418860808 0148696899 4140625E2',54(63)>
IMO, 64.4.to_d should return just that.
This is not a bug. f == f.to_d returns false, so if f == 1.to_d * f is true, then f.to_d == 1.to_d * f must be false because f != f.to_d. The == method for BigDecimal is intended to compare BigDecimals not BigDecimal to float. Sometimes the equality will work, but for some fs the BigDecimal representation is exact whereas the float is not.
Edit: See Is Floating Point Math Broken for more of an explanation.
Related
So I have this piece of code and it is this:
do
local function index(n,m)
return n*(n+1)//2 + m
end
local binomtable = {}
function binom3(n,m)
if n<0 or m<0 or m>n then return 0 end
if n=0 or m=0 or m=n then return 1 end
local i = index(n,m)
local v = binomtable[i]
if v then return v end
v = binom3(n-1,m-1) + binom3(n-1,m)
binomtable[i] = v
return v
end
end
and I would like to know what
if v then return v end
means.
Thank you!
The short answer is that if v then return v end returns the value v if it is truthy, i.e., if it is neither false nor nil. Otherwise the function continues by calculating a value for v, storing that value in binomtable, and finally returning it. The more interesting question is, why is the function doing all of this?
In the posted code, binom3 is a recursive function. With the recursive calls v = binom3(n-1,m-1) + binom3(n-1,m) there will be a lot of duplication of effort, meaning a lot of wasted space and time. Consider:
binom3(4, 2)
--> binom3(3, 1) + binom3(3, 2)
--> binom3(2, 0) + binom3(2, 1) + binom3(2, 1) + binom3(2, 2)
--> 1 + binom3(1, 0) + binom3(1, 1) + binom3(1, 0) + binom3(1, 1) + 1
Note how in the second reduction there are two identical terms:
binom3(2, 1) + binom3(2, 1)
There is no reason to calculate the term binom3(2, 1) twice, and doing so means that the pair of terms:
binom3(1, 0) + binom3(1, 1)
also must be calculated twice, as seen in the third reduction. It would be smart to calculate binom3(2, 1) only once, and to save the result for later use in the larger calculation. When m and n are larger and the number of calculations explodes exponentially this becomes a very important issue for performance both in the amount of memory required and in the amount of time required.
The posted code is using memoization to improve performance. When a calculation is made, it is stored in the table binomtable. Before any calculation is made, binomtable is consulted. First, v is set to the value of binomtable[i]; if this value is any truthy value (any integer is a truthy in Lua), then that value is simply returned without the need for recursive calculation. Otherwise, if nil is returned (i.e., no value has yet been stored for the calculation), the function continues with a recursive calculation. After completing the calculation, the new value is stored in binomtable for use the next time it is needed. This strategy saves a lot of wasted computational effort, and can make a huge difference in the performance of such recursive algorithms.
For your specific question of what
if v then return v end
means, is that if v, a variable, is not nil or false it is to return the value of the v variable and stop executing that function.
--Similar
function myfunc(input)
local MyVar = "I am a string and am not nil!"
if MyVar then
return "hi"
else
return "hello"
end
print("I am not seen because I am unreachable code!")
end
if this function was called it would always return "hi" instead of "hello" because MyVar is true, because it has a value. Also the print function below that will never get called because it stops executing the function after a return is called.
Now for your codes case it is checking a table to see if it has an entry at a certain index and if it does it returns the value.
my idea is the convert the 2 strings into byte, subtract and then check if they're 0 using a for loop like this
function match(str1, str2, callback)
local res = string.byte(str1) - string.byte(str2)
for i = 1, res(0) do
spawn(callback)
end
end
but that just doesn't work can anyone write me a code would appreciate...
rawequal(str1, str2) -- Compares two values without calling any metamethods
I'm creating a simple matrix like follows:
for x = 0, 50 do
current_level[x] = {}
for y = 0, 50 do
current_level[x][y] = grabTile();
end
end
After that i try to read it, but somehow the x is now a object not a number, while y seems perfectly fine!
How i try reading it:
for x,value in pairs(self.map) do
if value == ni then print("none"); return;end;
for y,object in pairs(value) do
if object == ni then print("none"); return;end;
object:render(x,y); -- Here x is an object
end
end
I'm new to working with lua, so i might be doing something obvious terribly wrong.
How would i make this work?
What i get for x is something like: table: 0x07c8d530
This value stays the same along the complete iteration
object:render(x,y); -- Here x is an object
This line is using colon syntax. It is a syntactic sugar for object.render(object,x,y) call.
So your render() function must have the first self argument declared either explicitly as function render(self, x, y) or implicitly with another syntactic sugar for definition: function object:render(x,y).
Unrelated hint. The first loop will be faster/smaller if transformed to:
for x = 0, 50 do
local row = {}
for y = 0, 50 do
row[y] = grabTile();
end
current_level[x] = row
end
I have a logic problem for an iOS app but I don't want to solve it using brute-force.
I have a set of integers, the values are not unique:
[3,4,1,7,1,2,5,6,3,4........]
How can I get a subset from it with these 3 conditions:
I can only pick a defined amount of values.
The sum of the picked elements are equal to a value.
The selection must be random, so if there's more than one solution to the value, it will not always return the same.
Thanks in advance!
This is the subset sum problem, it is a known NP-Complete problem, and thus there is no known efficient (polynomial) solution to it.
However, if you are dealing with only relatively low integers - there is a pseudo polynomial time solution using Dynamic Programming.
The idea is to build a matrix bottom-up that follows the next recursive formulas:
D(x,i) = false x<0
D(0,i) = true
D(x,0) = false x != 0
D(x,i) = D(x,i-1) OR D(x-arr[i],i-1)
The idea is to mimic an exhaustive search - at each point you "guess" if the element is chosen or not.
To get the actual subset, you need to trace back your matrix. You iterate from D(SUM,n), (assuming the value is true) - you do the following (after the matrix is already filled up):
if D(x-arr[i-1],i-1) == true:
add arr[i] to the set
modify x <- x - arr[i-1]
modify i <- i-1
else // that means D(x,i-1) must be true
just modify i <- i-1
To get a random subset at each time, if both D(x-arr[i-1],i-1) == true AND D(x,i-1) == true choose randomly which course of action to take.
Python Code (If you don't know python read it as pseudo-code, it is very easy to follow).
arr = [1,2,4,5]
n = len(arr)
SUM = 6
#pre processing:
D = [[True] * (n+1)]
for x in range(1,SUM+1):
D.append([False]*(n+1))
#DP solution to populate D:
for x in range(1,SUM+1):
for i in range(1,n+1):
D[x][i] = D[x][i-1]
if x >= arr[i-1]:
D[x][i] = D[x][i] or D[x-arr[i-1]][i-1]
print D
#get a random solution:
if D[SUM][n] == False:
print 'no solution'
else:
sol = []
x = SUM
i = n
while x != 0:
possibleVals = []
if D[x][i-1] == True:
possibleVals.append(x)
if x >= arr[i-1] and D[x-arr[i-1]][i-1] == True:
possibleVals.append(x-arr[i-1])
#by here possibleVals contains 1/2 solutions, depending on how many choices we have.
#chose randomly one of them
from random import randint
r = possibleVals[randint(0,len(possibleVals)-1)]
#if decided to add element:
if r != x:
sol.append(x-r)
#modify i and x accordingly
x = r
i = i-1
print sol
P.S.
The above give you random choice, but NOT with uniform distribution of the permutations.
To achieve uniform distribution, you need to count the number of possible choices to build each number.
The formulas will be:
D(x,i) = 0 x<0
D(0,i) = 1
D(x,0) = 0 x != 0
D(x,i) = D(x,i-1) + D(x-arr[i],i-1)
And when generating the permutation, you do the same logic, but you decide to add the element i in probability D(x-arr[i],i-1) / D(x,i)
I need to make decimal computations but sometimes the result is not exact.
0.009 + 0.001; // => 0.009999999999999998
How can I workaround that ?
You can use the decimal package. This package enables to make computations on decimal numbers without loosing precision like double operations.
Decimal.parse('0.2') + Decimal.parse('0.1'); // => 0.3
Decimal.parse('0.2') returns a new Decimal object that can be handled like num (by the way Decimal is not a num because num cannot be used as superclass or implemented).
To make your code shorter you can define a shortcut for Decimal.parse :
final d = Decimal.parse;
d('0.2') + d('0.1'); // => 0.3