Can someone explain to me NaN in Ruby? - ruby

I just found a bug in some number manipulations in my program and I'm getting a FloatDomainError (NaN)
So I started logging the number passed in with:
if(metric.is_a?(Numeric))
self.metric = metric
else
LOGGER.warn("metric #{metric} is not a number")
self.metric=0
end
But the number being passed in is NaN which apparently is_a?(Numeric) as I don't get my log warning, and it passes metric on to my metric= method, which is where I get my FloatDomainError
Now, correct me if I'm wrong, but doesn't it seem semantically wrong to have an NaN (Not A Number) be of type Numeric ?? Can someone explain this to me?
BTW using Jruby-1.4.1

I think that making NaN a number makes perfectly sense...
try 0.0 / 0.0 in irb -> the result is NaN (which in this case is infinity)
Infinity is mathematically kind of a number, but still, you can't express it with a datatype... in math you use a special symbol too...
PS: You can use metric.nan? to check it... then it should work as you expect...

IEEE 754 floating point numbers define -INFINITY +INFINITY and NotANumber to make it possible to react to lets say division by zero. you can also calculate with these for eg 2 + INF = INF
NaN isn't a uniqe ruby feature, they are numeric in java, c++, ... too

Related

Why does dividing by 1.8 not work, but multiplying by (5.0/9) does work?

I'm testing a simple program that converts Fahrenheit to Celsius, using Ruby.
This code returns 36.999999999 in terminal.
def ftoc(far)
return (far-32)/1.8
end
ftoc(98.6)
This code returns 37.
def ftoc(far)
return (far-32)*(5.0/9)
end
ftoc(98.6)
Can anyone tell me why? Thanks!!
The type of numbers you are using are called floating point numbers.
In general, any floating point arithmetic operation will introduce rounding errors. You cannot expect two floating-point results to be exactly equal if they were computed in different ways; you must have some tolerance for small errors.

Pascal double value is not exact, how to fix this?

I have been solving a programming challenge in UVA and got this problem, which is REALLY strange. Here is the flawed code:
program WTF;
begin
WriteLn(Trunc(2.01 * 100));
ReadLn();
end.
Obviously, I need to get 201 as Integer, but I get 200, this happens because Double somehow doesn't store the exact value... It's 2.01 = 2.00(9) for reasons unbeknownst to me, can someone explain this and provide a solution?
Edit: Yet, I figgured that using Round() instead of Trunc() fixes this... But still, why wouldn't Trunc() work?
Double stores numbers of the form s*2p where s and p are integers. The number 2.01 is not of the form s*2p for any integers s, p so it cannot be stored exactly in a Double.
The solution here is to round 2.01 * 100 to the nearest integer instead of truncating it. Although 2.01 is not exactly 2.01, it is only a little bit below. Rounding to the nearest integer would result in 201.
Note that if by 2.00(9) you mean 2.0099999999… repeating indefinitely, then 2.00(9)is not the Double you get when you write 2.01. The nearest Double to the real 2.01, and the number you got, is 2.0099999999999997868371792719699442386627197265625. It is of the form s * 2p: 9052235251014696 * 2-52

JDBC / Oracle Double value insertion fails [duplicate]

double r = 11.631;
double theta = 21.4;
In the debugger, these are shown as 11.631000000000000 and 21.399999618530273.
How can I avoid this?
These accuracy problems are due to the internal representation of floating point numbers and there's not much you can do to avoid it.
By the way, printing these values at run-time often still leads to the correct results, at least using modern C++ compilers. For most operations, this isn't much of an issue.
I liked Joel's explanation, which deals with a similar binary floating point precision issue in Excel 2007:
See how there's a lot of 0110 0110 0110 there at the end? That's because 0.1 has no exact representation in binary... it's a repeating binary number. It's sort of like how 1/3 has no representation in decimal. 1/3 is 0.33333333 and you have to keep writing 3's forever. If you lose patience, you get something inexact.
So you can imagine how, in decimal, if you tried to do 3*1/3, and you didn't have time to write 3's forever, the result you would get would be 0.99999999, not 1, and people would get angry with you for being wrong.
If you have a value like:
double theta = 21.4;
And you want to do:
if (theta == 21.4)
{
}
You have to be a bit clever, you will need to check if the value of theta is really close to 21.4, but not necessarily that value.
if (fabs(theta - 21.4) <= 1e-6)
{
}
This is partly platform-specific - and we don't know what platform you're using.
It's also partly a case of knowing what you actually want to see. The debugger is showing you - to some extent, anyway - the precise value stored in your variable. In my article on binary floating point numbers in .NET, there's a C# class which lets you see the absolutely exact number stored in a double. The online version isn't working at the moment - I'll try to put one up on another site.
Given that the debugger sees the "actual" value, it's got to make a judgement call about what to display - it could show you the value rounded to a few decimal places, or a more precise value. Some debuggers do a better job than others at reading developers' minds, but it's a fundamental problem with binary floating point numbers.
Use the fixed-point decimal type if you want stability at the limits of precision. There are overheads, and you must explicitly cast if you wish to convert to floating point. If you do convert to floating point you will reintroduce the instabilities that seem to bother you.
Alternately you can get over it and learn to work with the limited precision of floating point arithmetic. For example you can use rounding to make values converge, or you can use epsilon comparisons to describe a tolerance. "Epsilon" is a constant you set up that defines a tolerance. For example, you may choose to regard two values as being equal if they are within 0.0001 of each other.
It occurs to me that you could use operator overloading to make epsilon comparisons transparent. That would be very cool.
For mantissa-exponent representations EPSILON must be computed to remain within the representable precision. For a number N, Epsilon = N / 10E+14
System.Double.Epsilon is the smallest representable positive value for the Double type. It is too small for our purpose. Read Microsoft's advice on equality testing
I've come across this before (on my blog) - I think the surprise tends to be that the 'irrational' numbers are different.
By 'irrational' here I'm just referring to the fact that they can't be accurately represented in this format. Real irrational numbers (like π - pi) can't be accurately represented at all.
Most people are familiar with 1/3 not working in decimal: 0.3333333333333...
The odd thing is that 1.1 doesn't work in floats. People expect decimal values to work in floating point numbers because of how they think of them:
1.1 is 11 x 10^-1
When actually they're in base-2
1.1 is 154811237190861 x 2^-47
You can't avoid it, you just have to get used to the fact that some floats are 'irrational', in the same way that 1/3 is.
One way you can avoid this is to use a library that uses an alternative method of representing decimal numbers, such as BCD
If you are using Java and you need accuracy, use the BigDecimal class for floating point calculations. It is slower but safer.
Seems to me that 21.399999618530273 is the single precision (float) representation of 21.4. Looks like the debugger is casting down from double to float somewhere.
You cant avoid this as you're using floating point numbers with fixed quantity of bytes. There's simply no isomorphism possible between real numbers and its limited notation.
But most of the time you can simply ignore it. 21.4==21.4 would still be true because it is still the same numbers with the same error. But 21.4f==21.4 may not be true because the error for float and double are different.
If you need fixed precision, perhaps you should try fixed point numbers. Or even integers. I for example often use int(1000*x) for passing to debug pager.
Dangers of computer arithmetic
If it bothers you, you can customize the way some values are displayed during debug. Use it with care :-)
Enhancing Debugging with the Debugger Display Attributes
Refer to General Decimal Arithmetic
Also take note when comparing floats, see this answer for more information.
According to the javadoc
"If at least one of the operands to a numerical operator is of type double, then the
operation is carried out using 64-bit floating-point arithmetic, and the result of the
numerical operator is a value of type double. If the other operand is not a double, it is
first widened (§5.1.5) to type double by numeric promotion (§5.6)."
Here is the Source

Ruby number precision with simple arithmetic

I'm learning Ruby for fun, and for creating websites also (but that's irrelevant). While playing with it, i noticed something "weird"
When I compute 4.21 + 5 with irb, it answers 9.21 (weird, right?)
when I compute 4.23 + 5, it gives 9.23 (waw, that's definitely weird).
and when i type 4.22 + 5, it answers 9.21999... (w...wait! that's really weird).
Hence my question: what's going on?
I'd understand this behavior with division or really big numbers, but in this simple case....???
Does it mean that i can't develop an accounting app with Ruby?
Is there a patch or something to be applied? (to my brains, most likely)
You should read up on floating point representation in computers. This guide is a good place to start. Here's the short of it:
Because internally, computers use a
format (binary floating-point) that
cannot accurately represent a number
like 0.1, 0.2 or 0.3 at all.
When the code is compiled or
interpreted, your “0.1” is already
rounded to the nearest number in that
format, which results in a small
rounding error even before the
calculation happens.
By the way, I'm not sure why you think 4.21 + 5 = 9.21 or 4.23 + 5 = 9.23 is weird. If you think it's weird because one literal is an integer and one is a float, which ends up as a float response, that's how Ruby and some other languages handle differences in number types. It wouldn't be handy if Ruby dropped your float's precision and gave you just an integer back (9), so any integer literals are effectively changed to floats.
As for using floating-point numbers in a financial application, check out Developing financial application. The main takeaway is use the Decimal object vs. Float.
http://ruby-decimal.rubyforge.org/
This is the package you'd want to do reliable Floating Point maths in ruby. The Developint Financial Applications link doesn't reference it, but it makes the important point of using Decimal data types in your database.
Just noting this since it was non obvious for me :)

Handling Massive (high precision) Floats in Ruby

I'm making an application which is listening to prices being updated regularly, but occasionally my data source throws me something like "1.79769313486232e+308". The numbers that get sent will never by really big numbers (eg. "179769313486232e+308"), but as with the example above, they come with a lot of precision.
I'd be happy to drop everything after the first couple of decimal places, and end up with something like "1.798", but the following code isn't working for me:
irb(main):001:0> s = '1.79769313486232e+308'
=> "1.79769313486232e+308"
irb(main):002:0> ("%.3f" % s).to_f
(irb):2: warning: Float 1.79769313486232e+30... out of range
=> 0.0
Any graceful ways to handle these kind of numbers in Ruby?
You need to find out from your data source what those really big numbers mean. The price isn't actually 1.797e+308, but it probably also isn't 1.797. How you deal with those numbers depends entirely on what value you should be interpreting them as.
Update: I'm not sure you understand what this number means. 1.79769313486232e+308 is 1.79769313486232 times ten to the 308th power. It's a number with more than 300 digits to the left of the decimal point. This isn't a price, it's a mistake. It's the upper limit of what double-precision floating point can represent.
In other words, you're getting the equivalent of 0xFFFFFFFF or something like that, but interpreted as a floating point number.
That's right at the top of the range of "doubles". In Python for example it's converted to the special float called "inf".
The graceful way to handle this one might be to treat it as infinity
you could strip out extra decimals using regexp
>> s =~ /\.\d\d\d(\d+)/
>> s.gsub($1, '')
=> "1.797e+308"

Resources