Prevent FloatDomainError NaN - ruby-on-rails

In this calculation:
months = (saved_cents / spend_cents).to_f.floor
I get the following error:
FloatDomainError: NaN
I think saved_cents and spend_cents are floats, that's why I don't understand why I get this error.
What could be the reason for this error? And how can I fix it?

According to the documentation, a FloatDomainError is:
Raised when attempting to convert special float values (in particular Infinity or NaN) to numerical classes which don't support them.
In your code, a FloatDomainError occurs when both values are zero:
saved_cents = 0.0
spend_cents = 0.0
(saved_cents / spend_cents).floor
#=> FloatDomainError: NaN
Because zero divided by zero is NaN:
saved_cents / spend_cents
#=> NaN
and although NaN is a float, attempting to send it a floor message results in that error:
Float::NaN.floor
#=> FloatDomainError: NaN
What could be the reason for this error? And how can I fix it?
Double check your input. Maybe there's another bug which sets the values to 0.0 accidentally.

Related

prometheus sum one NaN value result into NaN. How to avoid it?

I have the following metrics in prometheus: it counts memcached command by sec:
sum (irate (memcached_commands_total{instance="memcached-instance"}[5m])) by (command)
Result:
{command="delete"} 0
{command="flush"} 0
{command="get"} 62.733333333333334
{command="incr"} 0
{command="set"} 93.43333333333334
{command="touch"} NaN
{command="cas"} 0
{command="decr"} 0
I want to count commands by sec (without separate rate for different commands). I have tried the following formula:
sum (irate (memcached_commands_total{instance="memcached-instance"}[5m]))
But the result is:
{} NaN
I expect about 155, but it is NaN. I suppose it is command="touch" the culprit. It is possible to exclude NaN from the sum?
I have figured it out:
sum (irate (memcached_commands_total{instance="memcached-instance"}[5m]) > 0)
returns the correct number. >0 does the trick.
The only way irate can produce a NaN is if it's being given a NaN as input. Given that irate is meant to work on counters, that should be impossible. I'd suggest looking into why memcached_commands_total is producing NaN.

Lua decimal precision loss

Can someone explain why in lua running:
return 256.65 * 1000000 + .000000005 - 256 * 1000000 gives 649999.99999997
whereas
return 255.65 * 1000000 + .000000005 - 255 * 1000000 and
return 268.65 * 1000000 + .000000005 - 268 * 1000000 give 650000.0 ?
From what i can see it seems to be an issue strictly for decimal 65 (and it seems also 15) and for whole numbers within the range 256 - 267. I know this is related to doing these calculations with floating points, but I'm still curious as to what is special about these values in particular
What is special about these values is that 0.65 is not a binary fraction (even though it is a decimal fraction), and so cannot be represented exactly in floating point.
For the record, this is not specific to Lua. The same thing will happen in C.
For the same reason that 10/3 is a repeating fraction in base 10. In base 3, dividing by 3 would result in whole numbers. In base 2 -- which is used to represent numbers in a computer -- the numbers you're producing similarly result in fractions that can be exactly represented.
Further reading.

lua decimals break around -0.1 to 0.1 (exclusive)

I have a Lua for loop that iterates through numbers from -1 to 1 by increments of 0.01, and is producing numbers as bad as 6.6613381477509e-016 in the range of -0.1 to 0.1 (exclusive)
I am using Lua in the LOVE engine (v 0.9.2), written in C++
I would much rather solve the problem than just receive an info dump of an explanation, but I'd rather that than nothing at all.
(also I do understand the general reason floats are inaccurate, so that may be left out of explanations)
You've already known the reason, here's a possible solution: don't loop with floating point numbers, use integers.
Instead of
for i = -1, 1, 0.01 do
use:
for i = -100, 100 do
print(i / 100)
end

How to process % to negative number in Visual Foxpro

How to do % to negative number in VF?
MOD(10,-3) = -2
MOD(-10,3) = 2
MODE(-10,-3) = -1
Why?
It is a regular modulo:
The mod function is defined as the amount by which a number exceeds
the largest integer multiple of the divisor that is not greater than
that number.
You can think of it like this:
10 % -3:
The largest multiple of 10 that is less than -3 is -2.
So 10 % -3 is -2.
-10 % 3:
Now, why -10 % 3 is 2?
The easiest way to think about it is to add to the negative number a multiple of 2 so that the number becomes positive.
-10 + (4*3) = 2 so -10 % 3 = (-10 + 12) % 3 = 2 % 3 = 3
Here's what we said about this in The Hacker's Guide to Visual FoxPro:
MOD() and % are pretty straightforward when dealing with positive numbers, but they get interesting when one or both of the numbers is negative. The key to understanding the results is the following equation:
MOD(x,y) = x - (y * FLOOR(x/y))
Since the mathematical modulo operation isn't defined for negative numbers, it's a pleasure to see that the FoxPro definitions are mathematically consistent. However, they may be different from what you'd initially expect, so you may want to check for negative divisors or dividends.
A little testing (and the manuals) tells us that a positive divisor gives a positive result while a negative divisor gives a negative result.

Strange for loop problem

I'm not sure if this is a bug or not, so I thought that maybe you folks might want to take a look.
The problem lies with this code:
for i=0,1,.05 do
print(i)
end
The output should be:
0
.05
.1
--snip--
.95
1
Instead, the output is:
0
.05
.1
--snip--
.95
This same problem happened with a while loop:
w = 0
while w <= 1 do
print(w)
w = w + .05
end
--output:
0
.05
.1
--snip--
.95
The value of w is 1, which can be verified by a print statement after the loop.
I have verified as much as possible that any step that is less than or equal .05 will produce this error. Any step above .05 should be fine. I verified that 1/19 (0.052631579) does print a 1. (Obviously, a decimal denominator like 19.9 or 10.5 will not produce output from [0,1] inclusive.) Is there a possibility that this is not an error of the language? Both the interpreter and a regular Lua file produce this error.
This is a rounding problem. The issue is that 0.05 is represented as a floating point binary number, and it does not have an exact representation in binary. In base 2 (binary), it is a repeating decimal similar to numbers like 1/3 in base 10. When added repeatedly, the rounding results in a number which is slightly more than 1. It is only very, very slightly more than 1, so if you print it out, it shows 1 as the output, but it is not exactly 1.
> x=0.05+0.05+0.05+0.05+0.05+0.05+0.05+0.05+0.05+0.05+0.05+0.05+0.05+0.05+0.05+0.05+0.05+0.05+0.05+0.05
> print(x)
1
> print(1==x)
false
> print(x-1)
2.2204460492503e-16
So, as you can see, although really close to 1, it is actually slightly more.
A similar situation can come up in decimal when we have repeating fractions. If we were to add together 1/3 + 1/3 + 1/3, but we had to round to six digits to work with, we would add 0.333333 + 0.333333 + 0.333333 and get 0.999999 which is not actually 1. This is an analogous case for binary math. 1/20 cannot be precisely represented in binary.
Note that the rounding is slightly different for multiplication so
> print(0.05*20-1)
0
> print(0.05*20==1)
true
As a result, you could rewrite your code to say
for i=0,20,1 do
print(i*0.05)
end
And it would work correctly. In general, it's advisable not to use floating point numbers (that is, numbers with decimal points) for controlling loops when it can be avoided.
This is a result of floating-point inaccuracy. A binary64 floating point number is unable to store 0.05 and so the result will be rounded to a number which is very slightly more than 0.05. This rounding error remains in the repeated sum, and eventually the final value will be slightly more than 1.0, and so will not be displayed.
This is a floating point thing. Computers don't represent floating point numbers exactly. Tiny rounding errors make it so that 20 additions of +0.05 does not result in precisely 1.0.
Check out this article: "What every programmer should know about floating-point arithmetic."
To get your desired behavior, you could loop i over 1..20, and set f=i*0.05
This is not a bug in Lua. The same thing happens in the C program below. Like others have explained, it's due to floating-point inaccuracy, more precisely, to the fact that 0.05 is not a binary fraction (that is, does not have a finite binary representation).
#include <stdio.h>
int main(void)
{
double i;
for (i=0; i<=1; i+=0.05) printf("%g\n",i);
return 0;
}

Resources