This question already has answers here:
What is a simple example of floating point/rounding error?
(9 answers)
Why is Lua arithmetic is not equal to itself? [duplicate]
(1 answer)
Closed 9 years ago.
Today morning I found a bug on my Lua Script, wich seem very weird. How can this evaluation fail this way? Examples can be tested in here
First example:
if( math.abs(29.7 - 30) <= 0.3 ) then
result = 1
else
result = 0
end
print("result = "..result )
-->> result = 0
Second example:
if( 0.3 <= 0.3 ) then
result = 1
else
result = 0
end
print("result = "..result )
-->> result = 1
Third example
if( math.abs(29.7-30) == 0.3 )then
print("Lua says: "..math.abs(29.7-30).." == 0.3")
else
print("Lua says: "..math.abs(29.7-30).." ~= 0.3")
end
-->> Lua says: 0.3 ~= 0.3 WHAT?
I am really confuse, and I would like to understand this to avoid similiar bugs in the future. Thanks
You are being hit by the fact that Lua uses (IEEE 754) 64-bit double-precision floating point numbers.
Look at the following examples
> print(0.3 == 0.3)
true
> print(0.3 <= 0.3)
true
> print(0.3 >= 0.3)
true
The actual value of 0.3 in memory is:
> print(string.format("%1.64f",math.abs(-0.3)))
0.2999999999999999888977697537484345957636833190917968750000000000
Now look at you example:
> print(math.abs(29.7-30) == 0.3)
false
> print(math.abs(29.7-30) >= 0.3)
true
> print(math.abs(29.7-30) <= 0.3)
false
The actual value of 29.7-30 is:
> print(string.format("%1.64f",29.7-30))
-0.3000000000000007105427357601001858711242675781250000000000000000
The actual value of math.abs(29.7-30) is:
> print(string.format("%1.64f", math.abs(29.7-30))
0.3000000000000007105427357601001858711242675781250000000000000000
And just for fun the value of math.abs(-0.3) is:
> print(string.format("%1.64f", math.abs(-0.3)))
0.2999999999999999888977697537484345957636833190917968750000000000
There are two solutions to you problem, the first is read What Every Computer Scientist Should Know About Floating-Point Arithmetic, and understand it :-). The second solution is to configure Lua to use another type for numbers, see Values and Types for hints.
Edit
I just thought of another way of "solving" the problem, but it is a bit of a hack, and not guarantied to always work. You can use fixed point numbers in lua by first converting the float to a string with a fixed precision.
In your case that would look something like:
a = string.format("%1.1f", math.abs(29.7 - 30))
print(a == "0.3")
or a bit more robust:
a = string.format("%1.1f", math.abs(29.7 - 30))
print(a == string.format("%1.1f", 0.3))
However you must make sure that you use a precision that is both adequate and the same for all you comparisons.
As we know, float point has a precision problem
Refer: http://lua-users.org/wiki/FloatingPoint
a = 1
if a < 1 then print("<1") end
Will never print "<1". Not unless you actually change a
Related
sorry for asking this question but I couldn't understand it
-- but i don't understand this code
ballDX = math.random(2) == 1 and 100 or -100
--here ballDY will give value between -50 to 50
ballDY = math.random(-50, 50)
I don't understand the structure what is (2) and why it's == 1
Thank you a lot
math.random(x) will randomly return an integer between 1 and x.
So math.random(2) will randomly return 1 or 2.
If it returns 1 (== 1), ballDX will be set to 100.
If it returns 2 (~= 1), ballDX will be set to -100.
A simple way to make a 50-50 chance.
That is a very common way of assigning variables in Lua based on conditionals. It’s the same you’d do, for example, in Python with “foo = a if x else b”:
The first function, math.random(2), returns either 1 or 2. So, if it returns 1 the part math.random(2) == 1 is true and so you assign 100 to the variable ballDX. Otherwise, assign -100 to it.
In lua
result = condition and first or second
basically means the same as
if condition and first ~= nil and first ~= false then
result = first
else
result = second
end
So in your case
if math.random(2) == 1 then
ballDX = 100
else
ballDX = -100
end
in other words, there is a 50/50 chance for ballDX to become 100 or -100
For a better understanding, a look at lua documentation helps a lot :
https://www.lua.org/pil/3.3.html
You can read:
The operator or returns its first argument if it is not false; otherwise, it returns its second argument:
So if the random number is 1 it will return the first argument (100) of the "or" otherwise it will return the second argument (-100).
I am trying to get the output as below:
The problem is from URI-1098 Sequence IJ 4.
My Code is:
void main() {
double x = 0;
double y = 1;
for(double i = x; i<=2; i+= .2){
for(double j=y; j <= y + 2; j++){
if(i==0 || i==1 || i==2){
print('I=${i.toStringAsFixed(0)} J=${j.toStringAsFixed(0)}');
}else{
print('I=${i.toStringAsFixed(1)} J=${j.toStringAsFixed(1)}');
}
}
y += 0.2;
}
}
And my output is:
I=0 J=1
I=0 J=2
I=0 J=3
I=0.2 J=1.2
I=0.2 J=2.2
I=0.2 J=3.2
I=0.4 J=1.4
I=0.4 J=2.4
I=0.4 J=3.4
I=0.6 J=1.6
I=0.6 J=2.6
I=0.6 J=3.6
I=0.8 J=1.8
I=0.8 J=2.8
I=0.8 J=3.8
I=1 J=2
I=1 J=3
I=1 J=4
I=1.2 J=2.2
I=1.2 J=3.2
I=1.2 J=4.2
I=1.4 J=2.4
I=1.4 J=3.4
I=1.4 J=4.4
I=1.6 J=2.6
I=1.6 J=3.6
I=1.6 J=4.6
I=1.8 J=2.8
I=1.8 J=3.8
I=1.8 J=4.8
I=2.0 J=3.0
I=2.0 J=4.0
I=2.0 J=5.0
I am not getting desired outputs for the last 3 lines of the output. Can anyone kindly show the the error in my logic.
Thanking you all in advance.
You're using doubles.
That's the issue here. You are adding 0.2 repeatedly to a value starting at 0, but 0.2 is not precisely representable as a double. The 0.2 literal really represents the double value 0.200000000000000011102230246251565404236316680908203125 which is close to 0.2, but not exactly there.
The values you get by adding 0.2 to itself ten times loses some precision along the way. It hits 1.0 precisely, but then the next addition needs to drop some bits so the next value is actually below 1.2. The final result is 1.9999999999999997779553950749686919152736663818359375 which is not == 2.0, so your check for == 2.0 doesn't trigger. When you ask for the value with one decimal, it does round to "2.0", so you can't tell unless you print the actual value.
There are multiple ways to get around the problem.
One is to not use doubles. If you keep the numbers as integers by multiplying them by ten, then you just need a way to create the string to print. That could be
String toPrint(int value) {
var string = value.toString();
var lead = string.substring(0, string.length - 1);
if (string.endsWith('0')) return lead;
return "$lead.${string.substring(string.length - 1)}";
}
Alternatively, you can keep using doubles, but do .toStringAsFixed(1) and then check whether the last digit is zero. If it is, cut off the last two characters before printing.
I am working with bitcoin source code want to set initial difficulty to 1 (I changed bdiff,nBits field). So I need to change pdiff as well. according to :
difficulty = difficulty_1_target / current_target (target is a 256
bit number)
difficulty_1_target can be different for various ways to measure
difficulty. Traditionally, it represents a hash where the leading 32
bits are zero and the rest are one (this is known as "pool difficulty"
or "pdiff"). The Bitcoin protocol represents targets as a custom
floating point type with limited precision; as a result, Bitcoin
clients often approximate difficulty based on this (this is known as
"bdiff").
Anyone knows where pdiff is stored ? Is it hard coded ?
I found the solution! It's not exactly a pdiff field in the code but there is a function in blockchain.cpp :
double GetDifficulty(const CBlockIndex* blockindex)
{
if (blockindex == nullptr)
{
return 1.0;
}
int nShift = (blockindex->nBits >> 24) & 0xff;
double dDiff =
(double)0x0000ffff / (double)(blockindex->nBits & 0x00ffffff);
while (nShift < 29)
{
dDiff *= 256.0;
nShift++;
}
while (nShift > 29)
{
dDiff /= 256.0;
nShift--;
}
return dDiff;
}
for bitcoin initial nBits is equal to 0x1d00ffff so dDiff field above becomes 1 and nshift is equal to 1D. For my private version I set nBits to 0x1f0fffff and should calculate dDiff like
double dDiff =(double)0x000ffff / (double)(blockindex->nBits & 0x00ffffff);
and nShift field for me is 0x1f so I changed while conditions to while(nShift < 31) andwhile (nShift > 31). by running command bitcoin-cli getdifficulty I got 1 as initial difficulty.
I have NoDataBase calculator app. It takes digit parameters from view, made calculations in controller with some methods and return answer. The issue is to show correct answer in view. I need to show exact float or integer.
I made some convertation, but it seems to looks ugly.
I wondering, how to implement DRY converter.
Links:
interest_calculator/index.html.erb
interest_calculator_controller.rb
number_to_number spec tests
persent_from_number spec tests
Rounding of float to 10 characters
# If accepted parameter is integer, then it shows in view as 5, when it
# is float, it shows as 5.1
#first_0 = params[:a_0].to_f % 1 != 0 ? params[:a_0].to_f : params[:a_0].to_i
#second_0 = params[:b_0].to_f % 1 != 0 ? params[:b_0].to_f : params[:b_0].to_i
#first_1 = params[:a_1].to_f % 1 != 0 ? params[:a_1].to_f : params[:a_1].to_i
#second_1 = params[:b_1].to_f % 1 != 0 ? params[:b_1].to_f : params[:b_1].to_i
integer_decimal_converter(#first_0, #second_0, #first_1, #second_1)
If you don't need global variables you can do something like this:
result = [:a_0, :b_0, :a_1, :b_1].map do |key|
value = params[key].to_f
value % 1 == 0 ? value.to_i : value
end
integer_decimal_converter(*result)
I'm trying to get Velocity to output the following Javascript code:
if ((whichOne+1) <= numCallouts ) {
whichOne = whichOne + 1; } else {
whichOne = 1;
}
Whenever I try to get Velocity to print a > or a <, it represents it as a & gt; or & lt;, which doesn't help me since I'm trying to get it to produce Javascript. I've tried:
#set ( $gt = ">" )
But even that ends up as a & gt;
Thanks in advance.
It is not a default behavior, the only reason I can think of why this is happening is if you have event ReferenceInsertionEventHandler configured with EscapeHtmlReference either in your velocity.config or in the Velocity initialization code.
Here is more info about events
I've had the same issue with Velocity - however, the problem is that I was using Velocity as an third party embedded language, and didn't have access to change the Velocity settings.
Unfortunately the only solution I was able to find was to rewrite the code without using greater than/less than explicitly, which admittedly is awful, but it's all about getting it to work...
Here is an example workaround for conditionals where you are trying to see if one number is larger than another:
if (n1 > n2) //Doesn't work because velocity turns this into if (n1 > n2)
if (n1 != n2)
{
diff = n1 - n2;
abs = abs(n1 - n2);
if (diff / abs == 1) //Greater than
else //if == -1 then less than
}
else //Equal
Maybe you are able to use the alternate symbols as described here :
http://velocity.apache.org/engine/devel/vtl-reference-guide.html#aifelseifelse_-_Output_conditional_on_truth_of_statements
So try to use if (n1 gt n2).