How to truncate floating point number in jscript? - jscript

How to truncate float value in Jscript?
eg.
var x = 9/6
Now x contains a floating point number and it is 1.5.
I want to truncate this and get the value as 1

x = Math.floor(x)
This will round the value of x down to the nearest integer below.

Math.round() should achieve what you're looking for, but of course it'll round 1.5 to 2. If you always want to round down to the nearest integer, use Math.floor():
var x = Math.floor(9 / 6);

Math.floor() only works as the OP intended when the number is positive, as it rounds down and not towards zero. Therefore, for negative numbers, Math.ceil() must be used.
var x = 9/6;
x = (x < 0 ? Math.ceil(x) : Math.floor(x));

Another solution could be:
var x = parseInt(9 / 6);
Wscript.StdOut.WriteLine(x); // returns 1
the main purpose of the parseInt() function is to parse strings to integers. So I guess it might be slower than Math.floor() and methods as such.

Related

How to get first 4 digits after the 0s in a decimal but keeping 0s • Python

I need the first 4 digits after the front 0s in a decimal while also keeping the 0s in the output without getting scientific notation.
Would like to take
0.0000000000000000000000634546534
and get
0.00000000000000000000006345 but not
6.345e-23.
But would also like to take
231.00942353246
and get
231.009423.
Thank you.
Here's one way using the decimal module.
import decimal
example = 0.0000000000000000000000634546534
x = decimal.Decimal(example)
sign = x.as_tuple().sign
digits = x.as_tuple().digits
exponent = x.as_tuple().exponent
figs = 4
result = decimal.Decimal((sign, digits[:figs], len(digits)+(exponent)-figs))
precision = -1 * (len(digits) + (exponent) - figs) # for this example: -1 * (99 + (-121) - 4)
print("{:.{precision}f}".format(float(result), precision=precision))
Result:
0.00000000000000000000006345
Note that Decimal stores 99 digits because of floating point imprecision. The example variable holds a float value (due to the initializer value) that is inherently imprecise. There is no way around this, unless you are able to represent the original float value as a string, that you can use to initialize the example variable.
There are cases, where the 4th digit shown will be wrong, because in the floating point representation that digit is represented as one lesser and the next digit is a 9, for example. To fix, this, we grab one more digit as well to use for rounding. This should work in most cases, as the imprecision should be within the nearest rounding threshold.
result = decimal.Decimal((0, digits[:figs + 1], len(digits)+(exponent)-figs-1))
Lastly, to handle the case where there are numbers before the decimal, we can simply store it, remove it, and re-add it:
whole_number_part = int(example)
example -= whole_number_part
...
result += whole_number_part
Altogether, we get:
import decimal
example = 231.00942353246
whole_number_part = int(example)
example -= whole_number_part
x = decimal.Decimal(example)
sign = x.as_tuple().sign
digits = x.as_tuple().digits
exponent = x.as_tuple().exponent
figs = 4
result = decimal.Decimal((0, digits[:figs + 1], len(digits)+(exponent)-figs-1))
result += whole_number_part
precision = -1 * (len(digits) + (exponent) - figs)
print("{:.{precision}f}".format(float(result), precision=precision))
Result:
231.009423

Trying to end up with two decimal points on a float, but keep getting 0.0

I have a float and would like to limit to just two decimals.
I've tried format(), and round(), and still just get 0, or 0.0
x = 8.972990688205408e-05
print ("x: ", x)
print ("x using round():", round(x))
print ("x using format():"+"{:.2f}".format(x))
output:
x: 8.972990688205408e-05
x using round(): 0
x using format():0.00
I'm expecting 8.98, or 8.97 depending on what method used. What am I missing?
You are using the scientific notation. As glhr pointed out in the comments, you are trying to round 8.972990688205408e-05 = 0.00008972990688205408. This means trying to round as type float will only print the first two 0s after the decimal points, resulting in 0.00. You will have to format via 0:.2e:
x = 8.972990688205408e-05
print("{0:.2e}".format(x))
This prints:
8.97e-05
You asked in one of your comments on how to get only the 8.97.
This is the way to do it:
y = x*1e+05
print("{0:.2f}".format(y))
output:
8.97
In python (and many other programming language), any number suffix with an e with a number, it is power of 10 with the number.
For example
8.9729e05 = 8.9729 x 10^3 = 8972.9
8.9729e-05 = 8.9729 x 10^-3 = 0.000089729
8.9729e0 = 8.9729 x 10^0 = 8.9729
8.972990688205408e-05 8.972990688205408 x 10^-5 = 0.00008972990688205408
8.9729e # invalid syntax
As pointed out by other answer, if you want to print out the exponential round up, you need to use the correct Python string format, you have many choices to choose from. i.e.
e Floating point exponential format (lowercase, precision default to 6 digit)
e Floating point exponential format (uppercase, precision default to 6 digit).
g Same as "e" if exponent is greater than -4 or less than precision, "f" otherwise
G Same as "E" if exponent is greater than -4 or less than precision, "F" otherwise
e.g.
x = 8.972990688205408e-05
print('{:e}'.format(x)) # 8.972991e-05
print('{:E}'.format(x)) # 8.972991E-05
print('{:.2e}'.format(x)) # 8.97e-05
(Update)
OP asked a way to remove the exponent "E" number. Since str.format() or "%" notation just output a string object, break the "e" notation out of the string will do the trick.
'{:.2e}'.format(x).split("e") # ['8.97', '-05']
print('{:.2e}'.format(x).split('e')[0]) # 8.97
If I understand correctly, you only want to round the mantissa/significand? If you want to keep x as a float and output a float, just specify the precision when calling round:
x = round(8.972990688205408e-05,7)
Output:
8.97e-05
However, I recommend converting x with the decimal module first, which "provides support for fast correctly-rounded decimal floating point arithmetic" (see this answer):
from decimal import Decimal
x = Decimal('8.972990688205408e-05').quantize(Decimal('1e-7')) # output: 0.0000897
print('%.2E' % x)
Output:
8.97E-05
Or use the short form of the format method, which gives the same output:
print(f"{x:.2E}")
rount() returns closest multiple of 10 to the power minus ndigits,
so there is no chance you will get 8.98 or 8.97. you can check here also.

Python floating point precision sum

I have the following array in python
n = [565387674.45, 321772103.48,321772103.48, 214514735.66,214514735.65,
357524559.41]
if I sum all these elements, I get this:
sum(n)
1995485912.1300004
But, this sum should be:
1995485912.13
In this way, I know about floating point "error". I already used the isclose() function from numpy to check the corrected value, but
how much is this limit? Is there any way to reduce this "error"?
The main issue here is that the error propagates to other operations, for example, the below assertion must be true:
assert (sum(n) - 1995485911) ** 100 - (1995485912.13 - 1995485911) ** 100 == 0.
This is problem with floating point numbers. One solution is having them represented in string form and using decimal module:
n = ['565387674.45', '321772103.48', '321772103.48', '214514735.66', '214514735.65',
'357524559.41']
from decimal import Decimal
s = sum(Decimal(i) for i in n)
print(s)
Prints:
1995485912.13
You could use round(num, n) function which rounds the number to the desired decimal places. So in your example you would use round(sum(n), 2)

math.sqrt function python gives same result for two different values [duplicate]

Why does the math module return the wrong result?
First test
A = 12345678917
print 'A =',A
B = sqrt(A**2)
print 'B =',int(B)
Result
A = 12345678917
B = 12345678917
Here, the result is correct.
Second test
A = 123456758365483459347856
print 'A =',A
B = sqrt(A**2)
print 'B =',int(B)
Result
A = 123456758365483459347856
B = 123456758365483467538432
Here the result is incorrect.
Why is that the case?
Because math.sqrt(..) first casts the number to a floating point and floating points have a limited mantissa: it can only represent part of the number correctly. So float(A**2) is not equal to A**2. Next it calculates the math.sqrt which is also approximately correct.
Most functions working with floating points will never be fully correct to their integer counterparts. Floating point calculations are almost inherently approximative.
If one calculates A**2 one gets:
>>> 12345678917**2
152415787921658292889L
Now if one converts it to a float(..), one gets:
>>> float(12345678917**2)
1.5241578792165828e+20
But if you now ask whether the two are equal:
>>> float(12345678917**2) == 12345678917**2
False
So information has been lost while converting it to a float.
You can read more about how floats work and why these are approximative in the Wikipedia article about IEEE-754, the formal definition on how floating points work.
The documentation for the math module states "It provides access to the mathematical functions defined by the C standard." It also states "Except when explicitly noted otherwise, all return values are floats."
Those together mean that the parameter to the square root function is a float value. In most systems that means a floating point value that fits into 8 bytes, which is called "double" in the C language. Your code converts your integer value into such a value before calculating the square root, then returns such a value.
However, the 8-byte floating point value can store at most 15 to 17 significant decimal digits. That is what you are getting in your results.
If you want better precision in your square roots, use a function that is guaranteed to give full precision for an integer argument. Just do a web search and you will find several. Those usually do a variation of the Newton-Raphson method to iterate and eventually end at the correct answer. Be aware that this is significantly slower that the math module's sqrt function.
Here is a routine that I modified from the internet. I can't cite the source right now. This version also works for non-integer arguments but just returns the integer part of the square root.
def isqrt(x):
"""Return the integer part of the square root of x, even for very
large values."""
if x < 0:
raise ValueError('square root not defined for negative numbers')
n = int(x)
if n == 0:
return 0
a, b = divmod(n.bit_length(), 2)
x = (1 << (a+b)) - 1
while True:
y = (x + n//x) // 2
if y >= x:
return x
x = y
If you want to calculate sqrt of really large numbers and you need exact results, you can use sympy:
import sympy
num = sympy.Integer(123456758365483459347856)
print(int(num) == int(sympy.sqrt(num**2)))
The way floating-point numbers are stored in memory makes calculations with them prone to slight errors that can nevertheless be significant when exact results are needed. As mentioned in one of the comments, the decimal library can help you here:
>>> A = Decimal(12345678917)
>>> A
Decimal('123456758365483459347856')
>>> B = A.sqrt()**2
>>> B
Decimal('123456758365483459347856.0000')
>>> A == B
True
>>> int(B)
123456758365483459347856
I use version 3.6, which has no hardcoded limit on the size of integers. I don't know if, in 2.7, casting B as an int would cause overflow, but decimal is incredibly useful regardless.

Implementation of excel's ROUND function

How would you implement a ROUND function:
ROUND(value, number of digits)
pi=3.14159265358979323
so, for example, ROUND(pi, 3) = 3.142
if you had these functions at your disposal:
AINT - truncates a value to a whole number
ANINT - calculates the nearest whole number
NINT - returns the nearest integer to the argument
or never minding the above functions, how is floating ROUND done at all ?
If you don't need to worry about overflow, here's how:
ROUND(value, nod) = NINT(value * POWER(10, nod)) / POWER(10, nod)
Otherwise you need to take care of the integer part and the float part separately.
I would assume, excuse my pseudo-code
function Round(value, num){
numsToSave = POWER(10, num);
value *= numsToSave ; //Get the numbers we don't want rounded on the left side of the floating point
value = AINT( ANINT(value) );
value /= numsToSave;
return value;
}
or
function Round(value, num){
numsToSave = POWER(10, num);
value *= numsToSave ; //Get the numbers we don't want rounded on the left side of the floating point
value = NINT(value);
value /= numsToSave;
return value;
}

Resources