If I input =numbervalue(4), I get the unsurprising result "4," if I input =numbervalue("m"), I get the unsurprising result "#value!," if I input =numbervalue("."), I get the unsurprising result "#value!," if I input =numbervalue(","), I get the very surprising result "0." Why is this and are there other characters that do this?
From the docs
If the Decimal_separator and Group_separator arguments are not specified, separators from the current locale are used.
You state you are using U.S. settings. Therefore your group separator is ,
If the group separator occurs before the decimal separator in the Text argument, the group separator is ignored.
As the only character in the string, the , is therefore ignored. That leaves you with an empty string
If an empty string ("") is specified as the Text argument, the result is 0.
So, as expected =numbervalue(",") returns 0
Related
I'm trying to convert dates in dd/mm/yy format to dd/mm/20yy format using re.sub and capture groups.
date = "25/11/20"
fixed_date = re.sub(r"(\d\d/\d\d/)(\d\d)", r"\120\2", date)
However, even though my regex seems to work on regex101.com, Python returns an imprintable character.
fixed_date
Out[42]: 'P20'
How can I get my string? In this case, it would be "25/11/2020"
Edit: date is actually a string
Do
fixed_date = re.sub(r"(\d\d\/\d\d\/)(\d\d)", r"\g<1>20\g<2>", date)
From re docs:
In string-type repl arguments, in addition to the character escapes and backreferences described above, \g<name> will use the substring matched by the group named name, as defined by the (?P<name>...) syntax. \g<number> uses the corresponding group number; \g<2> is therefore equivalent to \2, but isn’t ambiguous in a replacement such as \g<2>0. \20 would be interpreted as a reference to group 20, not a reference to group 2 followed by the literal character '0'. The backreference \g<0> substitutes in the entire substring matched by the RE.
I am working with IC9 codes and am creating somewhat of a mapping between codes and an integer:
proc format library = &formatlib;
invalue category other = 0
'410'-'410.99', '425.4'-'425.99' = 1
I have searched and searched, but haven't been able to find an explanation of how that range actually works when it comes to formatting.
Take the first range, for example. I assume SAS interprets '410'-'410.99' as "take every value between the inclusive range [410, 410.99] and convert it to a 1. Please correct me if I'm wrong in that assumption. Does SAS treat these seeming strings as floating-point decimals, then? I think that must be the case if these are to be numerical ranges for formatting all codes within the range.
I'm coming to SAS from the worlds of R and Python, and thus the way quote characters are used in SAS sometimes is unclear (like when using %let foo = bar... not quotes are used).
When SAS compares string values with normal comparison operators, what it does is compare the byte representation of each character in the string, one at a time, until it reaches a difference.
So what you're going to see here is when a string is input, it will be compared to the 'start' string and, if greater than start, then compared to the 'end' string, and if less than end, evaluated to a 1; if it's not for each pair listed, then evaluated to a zero.
Importantly, this means that some nonsensical results could occur - see the last row of the following test, for example.
proc format;
invalue category other = 0
'410'-'410.99', '425.4'-'425.99' = 1
;
quit;
data test;
input #1 testval $6.;
category=input(testval,category.);
datalines;
425.23
425.45
425.40
410#
410.00
410.AA
410.7A
;;;;
run;
410.7A is compared to 410 and found greater, as '4'='4', '1'='1', '0'='0', '.' > ' ', so greater . Then 410.7A is compared to 410.99 and found less, as '4'='4', '1'='1', '0'='0', '7' < '9', so less. The A is irrelevant to the comparison. But on the row above it you see it's not in the sequence, since A is ASCII 41x and that is not less than '9' (ASCII 39x).
Note that all SAS strings are filled to their full length by spaces. This can be important in string comparisons, because space is the lowest-valued printable character (if you consider space printable). Thus any character you're likely to compare to space will be higher - so for example the fourth row (410#) is a 1 because # is between and . in the ASCII table! But change that to / and it fails. Similarly, change it to byte(13) (through code) and it fails - because it is then less than space (so 410^M, with ^M representing byte(13), is less than start (410)). In informats and formats, SAS will treat the format/informat start/end as being whatever the length that it needs to - so if you're reading a 6 long string, it will treat it as length 6 and fill the rest with spaces.
Where would I insert this in my code? I have a inputs and a message box that I need to get to two decimals but I can't figure out where I should put it.
If you don’t want to print out the String and just want to format it for later use, you can use the static format method of the String class.
It works in exactly the same way as printf as far as formatting is concerned, but it doesn’t print the String, it returns a new formatted String.
String.format "%[argument number] [flags] [width] [.precision] type"
"%" is a special character in formatted String and it denotes start of formatting instruction. String.format() can support multiple formatting instruction with multiple occurrence of "%" character in formatting instruction.
"argument number" is used to specify correct argument in case multiple arguments are available for formatting.
"flags" is another special formatting instruction which is used to print String in some specific format for example you can use flag as "," to print comma on output.
"width" formatting option denotes minimum number or character will be used in output but in case if number is larger than width then full number will be displayed but if its smaller in length then it will be be padded with zero.
"precision" is using for print floating point formatted String, by using precision you can specify till how many decimal a floating point number will be displayed in formatted String.
"type" is the only mandatory formatting option and must always comes last in format String also input String which needs to be formatted must be with same type specified in "type" parameter.
public class StringFromatExample {
public static void main(String[] args) {
String s1 = String.format("%-4.5f %.20f", 35.23429837482,5.2345678901);
System.out.println(s1);
}
}
the output will be
35.23430 5.23456789010000000000
I'm using TryStrToFloat to convert string to Double variables. Everything works fine until string doesn't looks like '21e'. I get result of conversion 21.
It seems to me that compiler treats '21e' like number 21e0. String 21e1 gives result 210.
When I use Val function conversion works better. String '21e' gives error, but now '21e1' gives 210, '21e-1' gives number 2,1 etc.
How to make correct working of conversion. Should I detect letter 'e' in text, or is any simply way to convert ?
The documentation says:
Use TryStrToFloat to convert a string, S, to a floating-point value. S must consist of an optional sign (+ or -), a string of digits with an optional decimal point, and an optional mantissa. The mantissa consists of 'E' or 'e' followed by an optional sign (+ or -) and a whole number. Leading and trailing blanks are ignored.
Your input does not satisfy the conditions and so should be treated as an error.
You did not say so explicitly, but I presume that you claim that:
TryStrToFloat('21e', val)
returns True. If so, this is a bug and should be reported to Embarcadero. If you need to work around this then I suggest you code your own function that detects this case and handles it correctly.
On the other hand, if that function call returns False the function is behaving as designed and your mistake is to read the value in val.
Update
I can confirm that TryStrToFloat('21e', val) returns True. I tested on XE7 update 1. I submitted the following bug report to Embarcadero: https://quality.embarcadero.com/browse/RSP-9814
I have this code
String coNum = customerOrderLine.coNum.PadLeft(10 - customerOrderLine.coNum.Length);
I know that customerOrderLine.coNum = "123456" So I should end up with coNum being having 4 empty spaces at the front of it but I end up with it being "123456". How do I fix this? I tried PadRight in case that was the mistake and it also failed to work. I have to have the 4 empty spaces at the beginning to pass it into the API I am working on or it will fail.
PadLeft takes a total length as a parameter, so I think you want
String coNum = customerOrderLine.coNum.PadLeft(10);
This is because you have incorrectly specified the totalWidth parameter of the Pad* method.
From docs:
The number of characters in the resulting string, equal to the number
of original characters plus any additional padding characters.[...] If totalWidth is equal to the length of this instance, the method
returns a new string that is identical to this instance.
PadLeft does not specify a default character to pad with; your second argument should be the character to use for the pad, i.e.:
String coNum = customerOrderLine.coNum.PadLeft(10, ' ');
Edit: Also the first argument should be total desired length, not number of pad characters to add, per #Matthew's answer.