Is it posible to round the base of an of a number in E-notation: i.e.
4.454554e-63 ==> 4e-63
I know I can do it as follows, but I was wondering if anyone knows of an elegant way of doing it...
s = '4.454554e-63'
s.scan((/^(\d*).\d*e-(\d*)/) do |n, p|
puts "#{n.to_i}" + "e-" + "#{p}"
end
Many Thanks,
You may use % operator:
"%.0e" % s
The syntax of a format sequence:
%[flags][width][.precision]type
Field | Float Format
------+--------------------------------------------------------------
e | Convert floating point argument into exponential notation
| with one digit before the decimal point as [-]d.dddddde[+-]dd.
| The precision specifies the number of digits after the decimal
| point (defaulting to six).
i.e. precision should be 0 in your case
Related
I know there are similar questions so please bear with me.
I wish to generate approximately 50K codes for people to place orders - ideally no longer than 10 chars and can include letters and digits. They are not discount codes so I am not worried about people trying to guess codes. What I am worried about is somebody accidentally entering a wrong digit (ie 1 instead of l or 0 instead of O) and then the system will fail if by chance it is also a valid code.
As the codes are constantly being generated, ideally I don't want a table look-up validation, but an formula (eg if it contains an A the number element should be divisable by 13 or some such).
Select some alphabet (made of digits and letters) of size B such that there are no easy confusions. Assign every symbol a value from 0 to B-1, preferably in random order. Now you can use sequential integers, convert them to base B and assign the symbols accordingly.
For improved safety, you can append one or two checksum symbols for error detection.
With N=34 (ten digits and twenty four letters 9ABHC0FVW3YGJKL1N2456XRTS78DMPQEUZ), 50K codes require codes of length only four.
If you don't want the generated codes to be consecutive, you can scramble the bits before the change of base.
Before you start generating random combinations of characters, there are a couple of things you need to bear in mind:
1. Profanity
If your codes include every possible combination of four letters from the alphabet, they will inevitably include every four-letter word. You need to be absolutely sure that you never ask customers to enter anything foul or offensive.
2. Human error
People often make mistakes when entering codes. Confusing similar characters like O and 0 is only part of the problem. Other common mistakes include transposing adjacent characters (e.g. the → teh) and hitting the wrong key on the keyboard (e.g., and → amd)
To avoid these issues, I would recommend that you generate codes from a restricted alphabet that has no possibility of spelling out anything unfortunate, and use the Luhn algorithm or something similar to catch accidental data entry errors.
For example, here's some Python code that generates hexadecimal codes using an alphabet of 16 characters with no vowels. It uses a linear congruential generator step to avoid outputting sequential numbers, and includes a base-16 Luhn checksum to detect input errors. The code2int() function will return −1 if the checksum is incorrect. Otherwise it will return an integer. If this integer is less than your maximum input value (e.g., 50,000), then you can assume the code is correct.
def int2code(n):
# Generates a 7-character code from an integer value (n > 0)
alph = 'BCDFGHJKMNPRTWXZ'
mod = 0xfffffd # Highest 24-bit prime
mul = 0xc36572 # Randomly selected multiplier
add = 0x5d48ca # Randomly selected addend
# Convert the input number `n` into a non-sequential 6-digit
# hexadecimal code by means of a linear congruential generator
c = "%06x" % ((n * mul + add) % mod)
# Replace each hex digit with the corresponding character from alph.
# and generate a base-16 Luhn checksum at the same time
luhn_sum = 0
code = ''
for i in range(6):
d = int(c[i], 16)
code += alph[d]
if i % 2 == 1:
t = d * 15
luhn_sum += (t & 0x0f) + (t >> 4)
else:
luhn_sum += d
# Append the checksum
checksum = (16 - (luhn_sum % 16)) % 16
code += alph[checksum]
return code
def code2int(code):
# Converts a 7-character code back into an integer value
# Returns -1 if the input is invalid
alph = 'BCDFGHJKMNPRTWXZ'
mod = 0xfffffd # Highest 24-bit prime
inv = 0x111548 # Modular multiplicative inverse of 0xc36572
sub = 0xa2b733 # = 0xfffffd - 0x5d48ca
if len(code) != 7:
return -1
# Treating each character as a hex digit, convert the code back into
# an integer value. Also make sure the Luhn checksum is correct
luhn_sum = 0
c = 0
for i in range(7):
if code[i] not in alph:
return -1
d = alph.index(code[i])
c = c * 16 + d
if i % 2 == 1:
t = d * 15
luhn_sum += (t & 0x0f) + (t >> 4)
else:
luhn_sum += d
if luhn_sum % 16 != 0:
return -1
# Discard the last digit (corresponding to the Luhn checksum), and undo
# the LCG calculation to retrieve the original input value
c = (((c >> 4) + sub) * inv) % mod
return c
# Test
>>> print('\n'.join([int2code(i) for i in range(10)]))
HWGMTPX
DBPXFZF
XGCFRCN
PKKNDJB
JPWXNRK
DXGGCBR
ZCPNMDD
RHBXZKN
KMKGJTZ
FRWNXCH
>>> print(all([code2int(int2code(i)) == i for i in range(50000)]))
True
When I round of 12121.232323 to 2 digit decimal point like below
p 12121.232323.round(2)
it is printing
12121.23
But when I try to round()
211211.00000.round(2)
it's printing
211211.0
But I want
211211.00
How do I do that?
'%.2f' % 12121.232323
or
include ActionView::Helpers::NumberHelper
number_with_precision(value, :precision => 2)
What you seek is not exactly rounding but formatting.
You can select your float formatting like this:
p "%.2f" % 12121.0000
where the %.2f part means "show 2 decimal points"
I have a rather unorthodox homework assignment where I am to write a simple function where a double value is rounded to an integer with using only a while loop.
The main goal is to write something similar to the round function.
I made some progress where I should add or subtract a very small double value and I would eventually hit a number that will become an integer:
while(~isinteger(inumberup))
inumberup=inumberup+realmin('double');
end
However, this results in a never-ending loop. Is there a way to accomplish this task?
I'm not allowed to use round, ceil, floor, for, rem or mod for this question.
Assumption: if statements and the abs function are allowed as the list of forbidden functions does not include this.
Here's one solution. What you can do is keep subtracting the input value by 1 until you get to a point where it becomes less than 1. The number produced after this point is the fractional component of the number (i.e. if our number was 3.4, the fractional component is 0.4). You would then check to see if the fractional component, which we will call f, is less than 0.5. If it is, that means you need to round down and so you would subtract the input number with f. If the number is larger than 0.5 or equal to 0.5, you would add the input number by (1 - f) in order to go up to the next highest number. However, this only handles the case for positive values. For negative values, round in MATLAB rounds towards negative infinity, so what we ought to do is take the absolute value of the input number and do this subtraction to find the fractional part.
Once we do this, we then check to see what the fractional part is equal to, and then depending on the sign of the number, we either add or subtract accordingly. If the fractional part is less than 0.5 and if the number is positive, we need to subtract by f else we need to add by f. If the fractional part is greater than or equal to 0.5, if the number is positive we need to add by (1 - f), else we subtract by (1 - f)
Therefore, assuming that num is the input number of interest, you would do:
function out = round_hack(num)
%// Repeatedly subtract until we get a value that less than 1
%// i.e. the fractional part
%// Also make sure to take the absolute value
f = abs(num);
while f > 1
f = f - 1;
end
%// Case where we need to round down
if f < 0.5
if num > 0
out = num - f;
else
out = num + f;
end
%// Case where we need to round up
else
if num > 0
out = num + (1 - f);
else
out = num - (1 - f);
end
end
Be advised that this will be slow for larger values of num. I've also wrapped this into a function for ease of debugging. Here are a few example runs:
>> round_hack(29.1)
ans =
29
>> round_hack(29.6)
ans =
30
>> round_hack(3.4)
ans =
3
>> round_hack(3.5)
ans =
4
>> round_hack(-0.4)
ans =
0
>> round_hack(-0.6)
ans =
-1
>> round_hack(-29.7)
ans =
-30
You can check that this agrees with MATLAB's round function for the above test cases.
You can do it without loop: you can use num2str to convert the number into a string, then find the position of the . in the string and extract the string fron its beginning up to the position of the .; then you convert it back to a numebr with str2num
To round it you have to check the value of the first char (converted into a number) after the ..
r=rand*100
s=num2str(r)
idx=strfind(num2str(r),'.')
v=str2num(s(idx+1))
if(v <= 5)
rounded_val=str2num(s(1:idx-1))
else
rounded_val=str2num(s(1:idx-1))+1
end
Hope this helps.
Qapla'
I need to do integer division. I expect the following to return 2 instead of the actual 1:
187 / 100 # => 1
This:
(187.to_f / 100).round # => 2
will work, but does't seem elegant as a solution. Isn't there an integer-only operator that does 187 / 100 = 2?
EDIT
I'll be clearer on my use case since I keep getting down-voted:
I need to calculate taxes on a price. All my prices are in cents. There is nothing below 1 cent in the accountability world so I need to make sure all my prices are integers (those people checking taxes don't like mistakes... really!)
But on the other hand, the tax rate is 19%.
So I wanted to find the best way to write:
def tax_price(price)
price * TAX_RATE / 100
end
that surely returns an integer, without any floating side effect.
I was afraid of going to the floating world because it has very weird side-effects on number representation like:
Ruby strange issue with floating point multiplication
ruby floating point errors
So I found it safer to stay in the integer or the fractional world, hence my question.
You can do it while remaining in the integer world as follows:
def round_div(x,y)
(x + y / 2) / y
end
If you prefer, you could monkey-patch Fixnum with a variant of this:
class Fixnum
def round_div(divisor)
(self + divisor / 2) / divisor
end
end
187.round_div(100) # => 2
No – (a.to_f / b.to_f).round is the canonical way to do it. The behavior of integer / integer is (for example) defined in the C standard as "discarding the remainder" (see http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf page 82) and ruby uses the native C function.
This is a less know method, Numeric#fdiv
You use it like this : 187.fdiv(100).round
Not sure, but this might be what you have in mind.
q, r = 187.divmod(100)
q + (100 > r * 2 ? 0 : 1) # => 2
This should work for you :
Use syntax like this.
(number.to_f/another_number).round
Example:
(18.to_f/5).round
As #MattW already answer (+1), you'd have to cast your integers to floats.
The only other way that is less distracting can be to add .0 to your integer:
(187.0 / 100).round
However, usually we don't operate on concrete integers but variables and this method would be no use.
After some thoughts, I could:
have used BigDecimals but it feels like a bazooka to kill a bird
or I can use a custom method that wouldn't use floating division within the process, as #sawa suggests
def rounded_integer_div(numerator, denominator)
q, r = numerator.divmod(denominator)
q + (100 > r * 2 ? 0 : 1)
end
If what you want is to actually only increase the result by 1 if there's any remainder (e.g. for counting paging/batching), you can use the '%' (modula operation) for remainders checking.
# to add 1 if it's not an even division
a = 187
b = 100
result = a / b #=> 1
result += 1 if (a % b).positive?
#=> 2
# or in one line
result = (a / b) + ((a % b).zero? ? 0 : 1)
This seems horrible inefficient. Can someone give me a better Ruby way.
def round_value
x = (self.value*10).round/10.0 # rounds to two decimal places
r = x.modulo(x.floor) # finds remainder
f = x.floor
self.value = case
when r.between?(0, 0.25)
f
when r.between?(0.26, 0.75)
f+0.5
when r.between?(0.76, 0.99)
f+1.0
end
end
class Float
def round_point5
(self * 2).round / 2.0
end
end
A classic problem: this means you're doing integer rounding with a different radix. You can replace '2' with any other number.
Multiply the number by two.
round to whole number.
Divide by two.
(x * 2.0).round / 2.0
In a generalized form, you multiply by the number of notches you want per whole number (say round to .2 is five notches per whole value). Then round; then divide by the same value.
(x * notches).round / notches
You can accomplish this with a modulo operator too.
(x + (0.05 - (x % 0.05))).round(2)
If x = 1234.56, this will return 1234.6
I stumbled upon this answer because I am writing a Ruby-based calculator and it used Ruby's Money library to do all the financial calculations. Ruby Money objects do not have the same rounding functions that an Integer or Float does, but they can return the remainder (e.g. modulo, %).
Hence, using Ruby Money you can round a Money object to the nearest $25 with the following:
x + (Money.new(2500) - (x % Money.new(2500)))
Here, if x = $1234.45 (<#Money fractional:123445 currency:USD>), then it will return $1250.00 (#
NOTE: There's no need to round with Ruby Money objects since that library takes care of it for you!