How to keep arbitrary number of trailing 0s in float? - python-3.x

I need to keep track of the number of significant digits in a number (float or integer). Trailing zeroes after a decimal point are considered significant, e.g. in 12.0 there are 3 significant figures and in 12.00 there are 4. I thought to use something like len(str(number)) but this removes all but one of the trailing zeroes from floats. The format() function and str.format() method, often suggested for similar questions (in integer, in float, and float again) would both seemingly require me to know in advance how many decimal points I wanted. Is there a good way to go about this? Should I just require the number to be inputted as a string so that all trailing zeroes are preserved? The code I'm using to find significant figures is below. I believe that it works for all cases except that described above.
def __init__(self, value):
"""Initializes a Sigfig object with the given value and finds the number of significant figures in value"""
assert type(value)==int or type(value)==float or type(value)==Sigfig, "Sigfig value must be of type int, float, or Sigfig"
# I wanted to avoid values of type str so that I don't have to worry about inputs like Sigfig('55b')
self.value=value #This is to allow math with full value to avoid losing precision to rounding
self.valuestring=f'{value}'
#Remove leading zeroes before or after a decimal point and scientific notation
self.remlead0enot=self.valuestring.lstrip('0').lstrip('.').lstrip('0').split('e',1)[0]
#Account for ambiguous zeroes before implied decimal point e.g. 1000
if '.' not in self.valuestring and self.valuestring[-1]=='0':
self.sigfigs=len(self.remlead0enot.rstrip('0'))
#Account for floats e.g. 1.005 and ints e.g. 105
else:
self.sigfigs=len(self.remlead0enot)-1 if '.' in self.remlead0enot else len(self.remlead0enot)

I'm not sure what you want to achieve but if if your question is if you can make a float remember with how many trailing zeros it was stored with: No.
You can only define how many points after the comma should be included when you convert the float to a string. But the float itself has no concept about significant digits. (Aka: 3.000000f == 3.0f)
If you need to know the amount of trailing zeros, yes, you need the input to be a string.
When you already have a string though you can also just store how many numbers are after the ..
arg_as_str = "3.100"
decimal_points = len(arg.split(".")[1]) # 3
as_float = float(arg) # 3.1
...
output_as_str = f"{as_float:{decimal_points}f}" # "3.100"
Hope that was helpful.

You can look into the package mpmath. This package is made specifically for this purpose, to allow arbitrary precision of floats.
https://mpmath.org/

Related

SyntaxError: Unexpected number in JSON at position 182 [duplicate]

I'm importing some JSON files into my Parse.com project, and I keep getting the error "invalid key:value pair".
It states that there is an unexpected "8".
Here's an example of my JSON:
}
"Manufacturer":"Manufacturer",
"Model":"THIS IS A STRING",
"Description":"",
"ItemNumber":"Number12345",
"UPC":083456789012,
"Cost":"$0.00",
"DealerPrice":" $0.00 ",
"MSRP":" $0.00 ",
}
If I update the JSON by either removing the 0 from "UPC":083456789012, or converting it to "UPC":"083456789012", it becomes valid.
Can JSON really not accept an integer that begins with 0, or is there a way around the problem?
A leading 0 indicates an octal number in JavaScript. An octal number cannot contain an 8; therefore, that number is invalid.
Moreover, JSON doesn't (officially) support octal numbers, so formally the JSON is invalid, even if the number would not contain an 8. Some parsers do support it though, which may lead to some confusion. Other parsers will recognize it as an invalid sequence and will throw an error, although the exact explanation they give may differ.
Solution: If you have a number, don't ever store it with leading zeroes. If you have a value that needs to have a leading zero, don't treat it as a number, but as a string. Store it with quotes around it.
In this case, you've got a UPC which needs to be 12 digits long and may contain leading zeroes. I think the best way to store it is as a string.
It is debatable, though. If you treat it as a barcode, seeing the leading 0 as an integral part of it, then string makes sense. Other types of barcodes can even contain alphabetic characters.
On the other hand. A UPC is a number, and the fact that it's left-padded with zeroes to 12 digits could be seen as a display property. Actually, if you left-pad it to 13 digits by adding an extra 0, you've got an EAN code, because EAN is a superset of UPC.
If you have a monetary amount, you might display it as € 7.30, while you store it as 7.3, so it could also make sense to store a product code as a number.
But that decision is up to you. I can only advice you to use a string, which is my personal preference for these codes, and if you choose a number, then you'll have to remove the 0 to make it work.
One of the more confusing parts of JavaScript is that if a number starts with a 0 that isn't immediately followed by a ., it represents an octal, not a decimal.
JSON borrows from JavaScript syntax but avoids confusing features, so simply bans numbers with leading zeros (unless then are followed by a .) outright.
Even if this wasn't the case, there would be no reason to expect the 0 to still be in the number when it was parsed since 02 and 2 are just difference representations of the same number (if you force decimal).
If the leading zero is important to your data, then you probably have a string and not a number.
"UPC":"083456789012"
A product code is an identifier, not something you do maths with. It should be a string.
Formally, it is because JSON uses DecimalIntegerLiteral in its JSONNumber production:
JSONNumber ::
-_opt DecimalIntegerLiteral JSONFraction_opt ExponentPart_opt
And DecimalIntegerLiteral may only start with 0 if it is 0:
DecimalIntegerLiteral ::
0
NonZeroDigit DecimalDigits_opt
The rationale behind is is probably:
In the JSON Grammar - to reuse constructs from the main ECMAScript grammar.
In the main ECMAScript grammar - to make it easier to distinguish DecimalIntegerLiteral from HexIntegerLiteral and OctalIntegerLiteral. OctalIntegerLiteral in the first place.
See this productions:
HexIntegerLiteral ::
0x HexDigit
0X HexDigit
HexIntegerLiteral HexDigit
...
OctalIntegerLiteral ::
0 OctalDigit
OctalIntegerLiteral OctalDigit
The UPC should be in string format. For the future you may also get other type of UPC such as GS128 or string based product identification codes. Set your DB column to be string.
If an integer start with 0 in JavaScript it is considered to be the Octal (base 8) value of the integer instead of the decimal (base 10) value. For example:
var a = 065; //Octal Value
var b = 53; //Decimal Value
a == b; //true
I think the easiest way to send your number by JSON is send your number as string.

How to convert a string that represents a decimal number to a string that represents its binary form?

Take for example a string s="556852144786" that represents the decimal number n=556852144786. Is there a direct algorithm to transform it to s1="1000000110100110..." where 1000000110100110... is the binary representation of n?
I assume that you're looking for an algorithm that operates directly on strings, instead of converting to whatever integers are supported by the target language and using those?
There are various ways to do this. Here are two, though if you squint hard enough, they're almost the same algorithm.
Method 1: repeatedly divide the decimal string by two
In this method, we repeatedly divide the original decimal string by 2 (using decimal arithmetic), and keep track of the remainders: those remainders give you the bits of the result in reverse order.
Here's what that algorithm looks like, in Python. It's missing definitions of is_nonzero and divide_by_two. We'll provide those in a moment.
def dec_to_bin(s):
"""
Convert decimal string s to binary, using only string operations.
"""
bits = ""
while is_nonzero(s):
s, bit = divide_by_two(s)
bits += bit
# The above builds up the binary string in reverse.
return bits[::-1]
The algorithm generates the bits in reverse order, so we need a final reverse to give the resulting binary string.
The divide_by_two function takes a decimal string s and returns a new decimal string representing the quotient s / 2, along with the remainder. The remainder is a single bit, again represented as a string - either "0" or "1". It follows the usual digit-by-digit school-taught left-to-right division method: each step involves dividing a single digit, along with the carry brought in from the previous step, by two. Here's that function:
def divide_by_two(s):
"""
Divide the number represented by the decimal string s by 2,
giving a new decimal string quotient and a remainder bit.
"""
quotient = ""
bit = "0"
for digit in s:
quotient_digit, bit = divide_digit_by_two(bit, digit)
quotient += quotient_digit
return quotient, bit
We're left needing to define divide_digit_by_two, which takes a single digit plus a tens carry bit, and divides by two to get a digit quotient and a single-bit remainder. At this point, all inputs and outputs are strings of length one. Here we cheat and use integer arithmetic, but there are only 20 possible different combinations of inputs, so we could easily have used a lookup table instead.
def divide_digit_by_two(bit, digit):
"""
Divide a single digit (with tens carry) by two, giving
a digit quotient and a single bit remainder.
"""
digit, bit = divmod(int(bit) * 10 + int(digit), 2)
return str(digit), str(bit)
You can think of divide_digit_by_two as a primitive arithmetic operation that swaps two digits in different bases: it converts a nonnegative integer smaller than 20 represented in the form 10 * bit + digit into the same value represented in the form 2 * digit + bit.
We're still missing one definition: that of is_nonzero. A decimal string represents zero if and only if it consists entirely of zeros. Here's a quick Python test for that.
def is_nonzero(s):
"""
Determine whether the decimal string s represents zero or not.
"""
return s.strip('0') != ''
And now that we have all the bits in place, we can test:
>>> dec_to_bin("18")
'10010'
>>> dec_to_bin("556852144786")
'1000000110100110111110010110101010010010'
>>> format(556852144786, 'b') # For comparison
'1000000110100110111110010110101010010010'
Method 2: repeatedly multiply the binary string by 10
Here's a variant on the first method: instead of repeated divisions, we process the incoming decimal string digit by digit (from left to right). We start with an empty binary string representing the value 0, and each time we process a digit we multiply by 10 (in the binary representation) and add the value represented by that digit. As before, it's most convenient to build up the binary string in little-endian order (least-significant bit first) and then reverse at the end to get the traditional big-endian representation. Here's the top-level function:
def dec_to_bin2(s):
"""
Convert decimal string s to binary, using only string operations.
Digit-by-digit variant.
"""
bits = ""
for digit in s:
bits = times_10_plus(bits, digit)
return bits[::-1]
The job of the times_10_plus function is to take a binary string and a digit, and produce a new binary string representing the result of multiplying the value of the original by ten, and adding the value of the binary digit. It looks like this:
def times_10_plus(bits, digit):
"""
Multiply the value represented by a binary string by 10, add a digit,
and return the result as a binary string.
"""
result_bits = ""
for bit in bits:
digit, result_bit = divide_digit_by_two(bit, digit)
result_bits += result_bit
while digit != "0":
digit, result_bit = divide_digit_by_two("0", digit)
result_bits += result_bit
return result_bits
Note that we're using exactly the same arithmetic primitive divide_digit_by_two as before, but now we're thinking of it slightly differently: it's multiplying a single bit by ten, adding a carry digit, and turning that into a new bit (the least significant bit of the result) along with a new carry digit.
Efficiency notes
In the interests of clarity, I've left some Python-level inefficiencies. In particular, when building up the strings, it would be more efficient to build a list of bits or digits and then concatenate with a str.join operation right at the end. Also note that depending on the implementation language, it may make more sense to modify either the digit string or the bit string in-place instead of generating a new string at each step. I leave the necessary changes to you.

How to convert a String to a Float which is rounded UP to 4 decimal places

I have this string: "123,456.39213212"
I would like to to be converted to a float and rounded UP to the 4th decimal place.
According to an online tool I used I should get this number: 123456.3922
Please advise how I can do this in Groovy?
Thanks
It feels a bit hacky, but if your thousands separator is always , you can do something like this:
import java.math.RoundingMode
def input = "123,456.39213212"
def output = new BigDecimal(input.replaceAll(",", "")).setScale(4, RoundingMode.UP)
​Output:
123456.3922
Key parts are:
Replacing the comma with "" to have the string in a format that BigDecimal can work with and
Setting the scale to 4 using RoundingMode.UP (note: depending on your requirements regarding negative numbers you may want to use RoundingMode.CEILING instead)

Converting between a number to a string without num2str

For example, input is a=5678. How do you make b='5678'? (b is a String).
Not allowed to use str2num or any casting.
Is it possible to use log10? (I know how to do the reverse action).
[This is how I did the opposite (from string to num):
s = input('Enter a number: ','s');
x = sum(10.^(length(s-'0')-1:-1:0).*(s-'0'));
This looks like homework, so first here are some hints:
log10 may be useful to determine the number of digits.
mod can help to obtain each digit.
From your code for the reverse action: using successive powers of 10, as well as +'0' / -'0' to convert between digits and ASCII codes, may also be of help here.
And here's a possible approach using these hints (hover the mouse to find out):
b = char(mod(floor(a./10.^((ceil(log10(a))-1):-1:0)),10) + '0'):

Silverlight 4 StringFormat for double without decimals in XAML [duplicate]

I have a double value. I want to format this value in the format of x.yz. How do I do this? I keep getting digits truncated. Can someone tell me how to do this in C#?
Thanks!
Digits after decimal point
This example formats double to string with fixed number of decimal places. For two decimal places use pattern „0.00“. If a float number has less decimal places, the rest digits on the right will be zeroes. If it has more decimal places, the number will be rounded.
// just two decimal places
String.Format("{0:0.00}", 123.4567); // "123.46"
String.Format("{0:0.00}", 123.4); // "123.40"
String.Format("{0:0.00}", 123.0); // "123.00"
Next example formats double to string with floating number of decimal places. E.g. for maximal two decimal places use pattern „0.##“.
// max. two decimal places
String.Format("{0:0.##}", 123.4567); // "123.46"
String.Format("{0:0.##}", 123.4); // "123.4"
String.Format("{0:0.##}", 123.0); // "123"
Digits before decimal point
If you want a float number to have any minimal number of digits before decimal point use N-times zero before decimal point. E.g. pattern „00.0“ formats a float number to string with at least two digits before decimal point and one digit after that.
// at least two digits before decimal point
String.Format("{0:00.0}", 123.4567); // "123.5"
String.Format("{0:00.0}", 23.4567); // "23.5"
String.Format("{0:00.0}", 3.4567); // "03.5"
String.Format("{0:00.0}", -3.4567); // "-03.5"
Thousands separator
To format double to string with use of thousands separator use zero and comma separator before an usual float formatting pattern, e.g. pattern „0,0.0“ formats the number to use thousands separators and to have one decimal place.
String.Format("{0:0,0.0}", 12345.67); // "12,345.7"
String.Format("{0:0,0}", 12345.67); // "12,346"
Zero
Float numbers between zero and one can be formatted in two ways, with or without leading zero before decimal point. To format number without a leading zero use # before point. For example „#.0“ formats number to have one decimal place and zero to N digits before decimal point (e.g. „.5“ or „123.5“).
Following code shows how can be formatted a zero (of double type).
String.Format("{0:0.0}", 0.0); // "0.0"
String.Format("{0:0.#}", 0.0); // "0"
String.Format("{0:#.0}", 0.0); // ".0"
String.Format("{0:#.#}", 0.0); // ""
Align numbers with spaces
To align float number to the right use comma „,“ option before the colon. Type comma followed by a number of spaces, e.g. „0,10:0.0“ (this can be used only in String.Format method, not in double.ToString method). To align numbers to the left use negative number of spaces.
String.Format("{0,10:0.0}", 123.4567); // " 123.5"
String.Format("{0,-10:0.0}", 123.4567); // "123.5 "
String.Format("{0,10:0.0}", -123.4567); // " -123.5"
String.Format("{0,-10:0.0}", -123.4567); // "-123.5 "
Custom formatting for negative numbers and zero
If you need to use custom format for negative float numbers or zero, use semicolon separator „;“ to split pattern to three sections. The first section formats positive numbers, the second section formats negative numbers and the third section formats zero. If you omit the last section, zero will be formatted using the first section.
String.Format("{0:0.00;minus 0.00;zero}", 123.4567); // "123.46"
String.Format("{0:0.00;minus 0.00;zero}", -123.4567); // "minus 123.46"
String.Format("{0:0.00;minus 0.00;zero}", 0.0); // "zero"
http://www.csharp-examples.net/string-format-double/
Using format strings is explained in:
Standard Numeric Format Strings
Custom Numeric Format Strings
For example, try:
(0.56789).ToString("F2")
(0.56789).ToString("0.00").
Note that the resulting value is NOT truncated, but rounded in both cases, resulting in "0.57".
string.Format("{0:0.00}",yourdouble);
And maybe you'll find useful stick a paper with this http://john-sheehan.com/blog/wp-content/uploads/msnet-formatting-strings.pdf somewhere in your office
Tried something like this, using ToString?
doubleNumber = -1898300.1937;
Console.WriteLine(doubleNumber.ToString("F2", CultureInfo.InvariantCulture));
// Displays -1898300.19
I'm using Math.Round Method
Math.Round(yourdouble, 2)
You can also specify the rounding rule.
Try this:
number.ToString("0.00");
Also take a look at Custom Numeric Format Strings

Resources