Rails round method dont give's me what I want - ruby-on-rails-3

I have a problem with the round method. When I round a number like 1.876 it give me just 1.8 and I need to have 1.80 I use round(2).
My function is like:
#number.attr = (((#number1.to_f*number2.to_f)/100.0)).round(2).to_s

Round can't do that because 1.8 is a standard float but 1.80 is not a standard float.
irb(main)> 1.80.to_f
=> 1.8
The solution is to concatenate your result string with a zero if there is only 1 number after the '.'

1.9.3-p194 :001 > sprintf("%.2f", 1.8)
# => "1.80"
1.9.3-p194 :002 > sprintf("%.2f", 1.876)
# => "1.88"

Related

How to replace the list of decimal numbers in a string with another list of decimal numbers?

I need to replace the list of decimal numbers in a string with another list of decimal numbers. The following is a first try, that changes all decimal numbers with the same decimal number:
>>> re.sub (r"[-+]?\d*\.\d+f?", "1.0", "hello 1.2 3.4")
'hello 1.0 1.0'
I need something like my_replace below:
>>> my_replace (r"[-+]?\d*\.\d+f?", [1.0, 2.0], "hello 1.2 3.4")
'hello 1.0 2.0'
How can i implement my_replace with python's re module?
I don't think that you can use a list as replacement variables and iterate over them. So it can't handle unhashable objects (this is what python is complaining about). But it wouln'd be able to handle numerics as well (so it would need a list of strings but this is obviously hypothetical xD)
I would just loop over the string and compy everything that is not a decimal number to a new string and replacing the decimal numbers found.
text = "hello 1.2 3.4 don't replace an integer: 9 but this decimal number is too much: 0.0 (so use last value!)"
new_numbers = [42, 3.1415926535]
new_text = ''
idx_last = 0
for i, tx in enumerate(re.finditer(r'[-+]?\d*\.\d+f?', text)):
# add text before the number
new_text += tx.string[idx_last:tx.start()]
# add new number (but ensure that your are not overflowing the list of new numbers
new_text += str(new_numbers[min([i, len(new_numbers) - 1])])
# update text index
idx_last = tx.end()
# update remaining part of the text
new_text += text[idx_last:]
"hello 42 3.1415926535 don't replace an integer: 9 but this decimal number is too much: 3.1415926535 (so use last value!)"
Wrap it to a function and you have your my_replace() =)

Pascal- How to convert Real to Integer variable

I'm writing a task in pascal.
Everything is ok, just my result is not right.
I'm summing some numbers
Example: 2.3 + 3.4+ 3.3 = 9
But output shows: 9.000000 + EEE or something like that.
So- how to convert, to be only 9, not this REAL variable.
To actually convert:
var
i: integer;
...
i := round(floatVar);
To output only the integer part:
writeln(floatVar:9:0);
Let's consider this quite simpler equation:
3.5 + 2.5
What do you expect? 6, right? Let's try this code
write(3.5 + 2.5);
Unfortunately, it's a floating-point number, so it would produce a number represented in a scientific way:
6.00000000000E+00
or 6.0000000000 x 100, or 6 x 10o. Whatever, you only care about 6, who need this weird useless long number? So the idea is to cut off the decimal part and output to the console only the integer part, which can be done with this line of code:
write(3.5 + 2.5 : 0 : 0);
Ok, now it outputs a beautiful number as expected
6
Seems like the problem is solved, but you say that:
I'm summing some numbers
Example: 2.3 + 3.4+ 3.3 = 9
Ohh so that the evenly, beautiful integer is just randomly appeared? Here the problem comes, how do you expect this equation would output?
3.6 + 2.5
It should be 6.1, right? Let's try it with the worked line of code:
write(3.6 + 2.5 : 0 : 0);
And the output is...
6
Unexpected, right? So how about rounding to some decimal places, like 1?
write(3.5 + 2.5 : 0 : 1);
write(3.6 + 2.5 : 0 : 1);
Then, 3.5 + 2.5 = 6.0 and 3.6 + 2.5 = 6.1. But 6.0 may look quite long, so how to make it output 6 for 6.0 and 6.1 for 6.1?
Actually, you can't make the program auto-detect if a real variable contains an integer value because the way a real var is stored is completely different from an integer var (how different they are, please contact Google; but you can do it manually by making a function to do the job).
So my solution is, to be easy, making the output rounded to some decimal places, and that's it.
For purpose of showing pretty output on the screen you can use something like this:
Writeln(result:0:2);
Result on screen would be this:
9.00
What this means someone would ask? Well first number 0 means how wide filed is. if you say it's 0 then Pascal writes it at the very left side of screen. If you said writeln(result:5:2) result would be:
9.00
In other words i would print form the right side and leave 5 chars to do so.
Second number 2, in this example means you want that result printed with 2 decimal places. You can place it only if you want to print on screen value that is real, single, double, extended and so on.You can round to any number of decimals, and if you do writeln(result:0:0) you would get ouput:
9
If you are printing integer and want to have some length of field, lets sat 5 you would do: writeln(int:5). If you added :2 to the end you would get compile time error.
This all also works for something like this: writeln(5/3.5+sqrt(3):0:3),
You should know that this does not round variable itself but just formats output. This is also legal:
program test;
var
a:real;
n,m:integer;
begin
readln(a,m,n);
writeln(a:m:n);
end.
What i did here is i asked user if on how many decimals and with what length of field he wants to write entered number a. This can be useful so i'm pointing it out. Thank you for reading. I hope i helped
You can convert to string, get the int part, e convert to int number!
Or Float to Str than Str to Int:
nPage := StrToInt(FloatToStr(Int(nReg / nTPages))) + 1;

Simple Rails Calculation Incorrect

I can't figure out why a calculation is wrong. I'm trying to calculate the percent of time that the user scores over the median score in my Rails app.
controller
my_scores_over_median_count = 6
total_scores_over_median = 8
#my_over_median_percent = (my_scores_over_median_count / total_scores_over_median) * 100
When I add this to my controller:
puts my_scores_over_median_count
puts total_scores_over_median
puts #my_over_median_percent
I get:
6 (correct)
8 (correct)
0 (incorrect)
Can someone please help me understand why I'm getting 0 instead of 75 ? Thank you.
classic integer division problem. Change it to this and see it work:
my_scores_over_median_count = 6.0
total_scores_over_median = 8.0
#my_over_median_percent = (my_scores_over_median_count / total_scores_over_median) * 100
Ruby interprets 6 as a 'Fixnum' class, essentially an integer. We know this by:
1.9.3-p194 :001 > 6.class
=> Fixnum
Dividing any number by a Fixnum causes Ruby to do integer math which means any remainder gets thrown out. So:
1.9.3-p194 :004 > 4 / 5
=> 0
1.9.3-p194 :005 > 4 / 3
=> 1
If you have a variable that is a Fixnum, and you want to convert it to a float to force floating point division, you use the .to_f method:
1.9.3-p194 :007 > x = 4
=> 4
1.9.3-p194 :008 > y = 5
=> 5
1.9.3-p194 :009 > x / y
=> 0
1.9.3-p194 :010 > x.to_f / y
=> 0.8

A migration in a rails 3 app that will increase the value of an integer field by +1

I am trying to write a migration that will increase the value of an integer field by +1. I've tried several variations and done searches. What I am looking for is something like:
def self.up
User.update_all(:category => [:category + 1])
end
Thanks.
Maybe this will do it
User.update_all("category = (category + 1)")

Rails 3.1 SQL sum only negative numbers

I've got this code I'm using to insert data into Highcharts
def self.amount_on(date)
where("date(created_at) = ?",date).sum(:amount)
end
I would like to only sum an :amount if it's negative. Is this doable?
This should do it:
def self.amount_on(date)
where("amount > 0 AND date(created_at) = ?",date).sum(:amount)
end