Float Domain Error - ruby

Just got a "FloatDomainError" in my app, with the message "NaN" where the server would ordinarily describe the offense. The server error page points me to these lines (well, the first one):
n = ((self.weight * (c.percent)/100) / c.package_weight).to_i
n.times do
The problem seems to be with the .to_i, which is meant to convert what totals to 8.35 into an integer so I can do n.times do.
The problem is, if I take to_i away, I get an error telling me, logically enough, that there's no method "times" for the float 8.35. But I don't get why it's not letting me round off 8.35 to an integer. I've tried .floor too, but I get the FloatDomainError.
Ideas on how to round this off so I can get it to work?
Thanks!

This error means that you tried to convert a NaN value to int. NaN stands for "Not a number". That probably meants that your calculation is flawed and not result in 8.35. Maybe the value of c.package_weight is zero and you divide with it.

Related

Modulos function in freemarker truncating result

I'm trying to make a "complex calculation" in a freemarker template. The calculation calls for a modulus call. At first I kept simplifying my code, and finally just hardcoding values to try and figure out the cause, but it seems that freemarker's mod function ALWAYS returns int values?? but they're not even rounded, they're truncated. I need them rounded (.5 up would work). My most simplified code that does NOT work is this:
<#assign p_year_m1 = (2503.638 % 7.00)?float>
the longer version is:
<#assign p_year_m1 = ((bdy_m1 + (bdy_m1/4.0)-(bdy_m1/100.0)+(bdy_m1/400.0)))%7>
So the correct answer should be 4.638, rounds up to 5, but I'm getting 4.00 even if I wrap ?string[0.00] around it.
What am I missing? Surely there has to be a way to make this work! If not, I guess I'd need help constructing a work around to get similar results.
Thanks.
PS - the var, p_year_m1 is not intialized before this, so I believe if I try to store a float in there it should hold a float.
This is the calculation I'm trying to replicate
I can confirm that % gives the remainder of integer division. It casts (truncates) both arguments to integers, and then calculates the remainder. It's weird for sure, but can't be changed because of backward compatibility. The main application is calculating "zebra tables" and such, where it's might as well desirable, I don't know... it had just get in like that in the early times of the project, and then stuck.

How to pass a variable with decimal places in Ruby

I am having real difficulty with this and every answer I have seen doesnt seem to work. I have been able to pass a value such as 1.44 as 1.00 but the two decimal values are being lost. I have a number of values passed from a from which i then want to submit to an api via a call. The code is below:
IncomeWagesWeekly = params[:WagesWeekly].to_i
How do i ensure that when this is passed the two decimal places are present. Thanks for any help.
You don't have in Ruby language such thing as fixed digits after decimal point.
1 is the same as 1.00 as it was rightfully mentioned before in comment (almost the same).
If you don't check it's type like that:
1.is_a? Integer # => true
1.is_a? Float # => false
it is all the same.
Just use 1.44.to_i.
If by some reason you want to have an instance of Float instead use to_f method. To crop number explicitly you should use round, or ceil, or floor method:
1.44.round.to_f # => 1.0
1.55.round.to_f # => 2.0
1.44.ceil.to_f # => 2.0
1.55.ceil.to_f # => 2.0
1.44.floor.to_f # => 1.0
1.55.floor.to_f # => 1.0
Maybe don't try to make in integer and use to_f instead. Also consider any sprintf( "%0.02f", your_number), but it returns string.
First, it seems that you want to do fixed-point arithmetic here. So, using a floating point number is not the right choice, since floating point calculations can produce mathematically incorrect results.
A solution for this would be either to stick with Integers (as has been suggested already), or to use the data type BigDecimal, which is defined in the Ruby standard library, and in particular its methods fix, frac and to_digits.
Now to your database: You didn't say what database you are using, and how you pass the values to it, but in general, it is a bad idea to store a non-integer value into a database-field which is supposed to accept integers. As you observed, the fractional part was dropped. Correct behaviour.
You could redefine your database schema, or you can convert your decimal value by yourself into something which matches the field definition in the database. Which way to go, depends on what you want to actually do with this value afterwards. For instance, if you just want to display it, but not perform any calculations, you could use a string. Or, if you know that the number of fractional digits don't exceed a certain limit, you could define a suitable numeric format for the database column - etc.

Comparing two virtually identical BigDecimal numbers in Ruby on Rails

I got a little problem that I really would like to understand. I am using assert_equal to compare two BigDecimal numbers that are supposed to be identical. They actually are except a very little tiny fraction, see below:
-#<BigDecimal:7f4b40e8de78,'0.4021666666 6666666666 666666667E2',36(45)>
+#<BigDecimal:7f4b40e85db8,'0.4021666666 6666666666 6666668E2',36(63)>
I use assert_in_delta in order to not fail the test cases. So I got a reasonable workaround. I do wonder though whether it would be possible to have it equal:
assert_equal (241.30.to_d/6), model.division_function
The model's division_function does exactly the same. It divides a BigDecimal of value 241.3 by the length of an array, which is 6.
There seems to be a very tiny difference in the precision.
I would like to know where that might come from?
Is there a way I can control precision more accurately?
EDIT
I am using Mongoid. It is worth to note that Mongoid offers BigDecimal as a field type, but it is stored as a string. However, I don't think this is the problem. I believe it is a Ruby thing.
EDIT
I got a little further with an example which hints that it is a Ruby issue and not directly related to Rails. Please see below:
irb(main):041:0* amount1 = BigDecimal("241.3")
=> #<BigDecimal:7f49bcb03558,'0.2413E3',18(18)>
irb(main):042:0> amount2 = BigDecimal("1800")
=> #<BigDecimal:7f49bcaf3400,'0.18E4',9(18)>
irb(main):043:0> rate = amount1 / amount2
=> #<BigDecimal:7f49bcae8398,'0.1340555555 5555555555 5555556E0',27(45)>
irb(main):044:0> rate * amount2 #should return amount1 = 241.3, but it does not :-(
=> #<BigDecimal:7f49bcad6a30,'0.2413000000 0000000000 00000008E3',36(45)>
irb(main):045:0>
I reported the bug to the Ruby core team. However, this is not a bug as you can see in the rejection response.
BigDecimal, though offers arbitrary precision, cannot represent numbers like 1/3 precisely. Thus during some arithmetic you can encounter imprecisions.
You can use Rational in Ruby for exact numbers. Exercise caution when doing arithmetics if you wish to keep the result exact.

Xcode - Debugger does not show correct value

Let's try this :
float test = 3.56;
float roundedVal = round(test * 10.0f) / 10.0f;
NSLog (#"%f", roundedVal);
Why does tthe NSLog shows 3.600000, and the debugger 3.5999999 ?
What is the correct value I can count on ?
A float is not very precise and you can't expect them to be displayed accurately from one "view" to the next depending on a variety of factors. Read What Every Computer Scientist Should Know About Floating-Point Arithmetic.
Boils down to this: use double if you really want precision.
The correct value is the debugger. You can see this with a simplified version of the code above:
float test = 3.5999999;
NSLog (#"%f", test);
In this case, you get the same results as what you mentioned above: the log states 3.600000 and the debugger states it is 3.5999999. In all cases, the debugger has the correcrt value over an NSLog. When we dig a bit deeper, we can see that NSLog is slightly massaging the float value.
In reality - you should probably use a double here to maintain the precision you are looking for.
There is no "correct value". The expected value "3.6" does not have an exact binary representation. Therefore, the value the computer uses internally is an approximation. When printing the value, it needs to convert that back to decimal. In your case, the binary representation is likely slightly less than 3.6. NSLog happens to round it up, while the debugger rounds it down.
Using double instead of float, like the accepted answer says, does not change anything in this.

Calculating Event Horizons in Ruby

this is my first post here. I started using Ruby just 2 days ago and think it is an amazing language, however I have been getting stuck. My problem is I am wanting to calculate the event horizon of a black hole given an input defined in the code as "m" This will then be put into a calculation and the size then printed out to the screen. I did need it to be in binary and thats where I am having the issue.
Here is my code so far.
#Event Horizon Calculation Program
G = 6.67*10**-11
m = 20
C = 200000
R = G*m/(C**2)
puts "Here is the result in Binary."
R.to_i(2)
puts R
Now I do realise that the number are not accurate, that dosen't matter at the moment. I just need the function to work.
Thankyou,
Ross.
Your post is not even in a format of asking a question, but guessing from what you wrote, it seems that you are asking how to change your code so that it accepts an input to m and outputs the result. My answer is based on this assumption.
In order to take an input, use the 'gets' method. So, you may want to replace your 'm = 20' line with:
m = gets.to_f
'gets' accepts an input as a string, so you need to convert it to a numeric. to_f changes a string into a float. You can use to_i instead if you want an integer.
You have a line 'R.to_i(2)', and it seems like you want to output this, but you have two problems here. First of all, whatever that creates, it is only creating something in that position, and does not change the value of R, so, in effect, it actually does nothing. Second, ruby can accept numerals in source code written in different bases such decimal, binary, hex, etc., but it only has one internal representation, and you cannot output a numeral in binary. For your purpose, you need to convert it to a string that corresponds to a binary expression. For that, use the 'to_s' method. In fact, the 'to_i' method does not take an argument. Delete your line 'R.to_i(s)', and replace the line 'puts R' with:
puts R.to_s(2)

Resources