Is Excel's FALSE like infinity? - excel

Why does =FALSE<10000000000 evaluate as FALSE and =FALSE>10000000000 evaluate as TRUE? I have tried some different numbers and this seems to always be the case.

This is by design. Search help for "Troubleshoot Sort" to see the default sort order.
In an ascending sort, Microsoft Excel uses the following order.
Numbers: Numbers are sorted from the smallest negative number to the largest positive number.
Alphanumeric sort: When you sort alphanumeric text, Excel sorts left to right, character by character. For example, if a cell contains the text "A100," Excel places the cell after a cell that contains the entry "A1" and before a cell that contains the entry "A11."
Text and text that includes numbers are sorted in the following order:
0 1 2 3 4 5 6 7 8 9 (space) ! " # $ % & ( ) * , . / : ; ? # [ \ ] ^ _ ` { | } ~ + < = > A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
Apostrophes (') and hyphens (-) are ignored, with one exception: If two text strings are the same except for a hyphen, the text with the hyphen is sorted last.
Logical values: In logical values, FALSE is placed before TRUE.
Error values: All error values are equal.
Blanks: Blanks are always placed last.
The default sort order matters because that is how Excel was designed to compare different data types. Logical values are always after text and numbers. Error values are always after that. Blanks are always last. When you use comparison operators (<, <=, =, etc.) it uses the same comparison algorithm as the sort (or more likely, the sort alogrithm uses the comparison operator code, which makes them identical).
TRUE<>1 according to the sort order, but --TRUE=1. The formula parser recognized that you're trying to negate something. If it's a Boolean value, it converts it to 0 or 1. There's nothing 0-ish or 1-ish about the Boolean value, it's just the result of an internal Type Coercion function. If you type --"SomeString" it does the same thing. It sends the string into the Type Coercion function that reports back 'Unable to coerce' and ends up as #VALUE! in the cell.
That's the 'Why it behaves that way' answer. I don't know the 'Why did they design it that way' answer.

Obviously the boolean TRUE/FALSE are different data types to numbers. Check this (http://msdn.microsoft.com/en-us/library/office/bb687869.aspx) to see that boolean variables are stored in 2-byte (or whatever a short integer is for a certain architecture). However this is the memory where the data is stored, because excel actually has a special data class for boolean vars. Specifically: xltypeNum for numbers, xltypeStr for strings, and xltypeBool for what we discuss.
The relations between same types is clear, now what TRUE<1000 does?? probably nothing meaningful-useful.
Ways to overcome this issue:
=ABS(BOOLEAN_VAR), i.e. =ABS(FALSE) --> 0 and =ABS(TRUE) --> 1
or
=INT(BOOLEAN_VAR), i.e. =INT(FALSE) --> 0 and =INT(TRUE) --> 1
or
=BOOLEAN_VAR*1, i.e. =FALSE*1 --> 0 and =TRUE*1 --> 1
or
=+BOOLEAN_VAR, i.e. =+FALSE --> 0 and =+TRUE --> 1
As you see in these ways you force excel to output a numeric type of data, either by providing the boolean into a function or using the boolean var in an expression.

Related

How to get first significant figure from a number in Excel?

I have a column of numbers in Excel 2016. The numbers span many orders of magnitude, but are all positive. Some are less than zero. How can I return the first significant figure of each cell in a new column?
For example, for the number 1.9 the result should be 1. For the number 0.9 the result should be 9.
Things I've tried:
Using LEFT() to get the first character. This works for values greater than 1, but for numbers between 0 - 1 it returns 0 (that is, LEFT(0.3, 1) returns 0). I've tried using this with scientific notation formatting and it returns the same result.
I've searched Google and SO for solutions to this problem. There are many posts about rounding to significant figures, but I'm looking to truncate, not round.
Reading through Office's online docs regarding scientific notation.
You could use scientific notation:
=LEFT(TEXT(A1,"0.000000000000000E+00"))
Note: You can only have 15 digits of precision in Excel so this should be OK.
you can multiply the number by a factor of 10 significant enough to deal with any 0 not wanted:
=--LEFT(A1*10^LEN(A1),1)
Read the cell value as text, replace dots and zeros (. / 0) with nothing, return the leftmost "character"; multiply it by 1 to coerce it back into a number:
=LEFT(SUBSTITUTE(SUBSTITUTE(TEXT(A1,"#"),".",""),"0",""))*1
You can also create a custom UDF (User Defined Function) that uses Regular Expressions to accomplish this task. This would require copy/paste VBA knowledge, as well as you setting a reference to:
Microsoft VBScript Regular Expressions 5.5
(which can be done by going to the VBE (Alt+F11), Tools > References. Then check the box of the reference listed above)
Paste the following UDF into a standard code module within the VBE:
Public Function SigNum(ByVal InputNumber As Double) As Long
Dim s As SubMatches
With New RegExp
.Pattern = "\.0*([^0])|^([^0])"
If .test(InputNumber) Then
Set s = .Execute(InputNumber)(0).SubMatches
If s(0) > 0 Then ' This is before the period
SigNum = s(0)
Else
SigNum = s(1)
End If
End If
End With
End Function
On your worksheet, you would be able to use your newly created formula as such:
=SigNum(A1)
You can see what it matches in the example on regex101. When viewing this site, green highlighted numbers are what would be returned if the value is < 0, and red would be what is returned if the value > 0). If the value = 0, this will return 0.
Breaking Down the Pattern
Here's how the pattern \.0*([^0])|^([^0]) works. First, you can see that there is a |, which essentially acts like an Or statement, so we will split these into two sections.
First Section \.0*([^0])
\. will match a literal period. This ensures that we are looking at a value that is less than 0.
0* matches all zeros, 0 to unlimited * times. We use * (zero to unlimited) instead of + (1 to unlimited) because a zero is not required to be in front of the significant number - but the zero itself isn't significant.
[^0] This is a negated character class [^...]. This means it will match anything that is not in this class. Since our significant number should be a value other than zero, we do not want to match a zero. And because it's surrounded by a capturing group (...), this is what is returned back to the function.
Second Section ^([^0])
We've established that since the first section didn't match, then the value must be greater than 0.
^ this is an anchor point that matches the beginning of the string. On the first section we didn't require it because we essentially used the period \. as our anchor. Since our value is greater than 0, we need to ensure we are starting from the absolute left of the input number.
(...) Capturing Group. Anything within this group will be returned as a submatch and ultimately back to the function as it's return value.
[^0] Negated Character class. It will match anything except a 0.

Counting the occurence of substrings in matlab

I have a cell, something like this P= {Face1 Face6 Scene6 Both9 Face9 Scene11 Both12 Face15}. I would like to count how many Face values, Scene values, Both values in P. I don't care about the numeric values after the string (i.e., Face1 and Face23 would be counted as two). I've tried the following (for the Face) but I got the error "If any of the input arguments are cell arrays, the first must be a cell array of strings and the second must be a character array".
strToSearch='Face';
numel(strfind(P,strToSearch));
Does anyone have any suggestion? Thank you!
Use regexp to find strings that start (^) with the desired text (such as 'Face'). The result will be a cell array, where each cell contains 1 if there is a match, or [] otherwise. So determine if each cell is nonempty (~cellfun('isempty', ...): will give a logical 1 for nonempty cells, and 0 for empty cells), and sum the results (sum):
>> P = {'Face1' 'Face6' 'Scene6' 'Both9' 'Face9' 'Scene11' 'Both12' 'Face15'};
>> sum(~cellfun('isempty', regexp(P, '^Face')))
ans =
4
>> sum(~cellfun('isempty', regexp(P, '^Scene')))
ans =
2
Your example should work with some small tweaks, provided all of P contains strings, but may give the error you get if there are any non-string values in the cell array.
P= {'Face1' 'Face6' 'Scene6' 'Both9' 'Face9' 'Scene11' 'Both12' 'Face15'};
strToSearch='Face';
n = strfind(P,strToSearch);
numel([n{:}])
(returns 4)

Why is Excel VBA rounding my integer division results?

I'm writing a VBA macro in Excel 2002 to manipulate date from a device that gives 10 values on each of 4 channels.
When I try to divide an integer by another integer to calculate the row and column, the result shows that it's using bankers rounding, as if it was a floating point variable.
Sub TestRounding()
Dim Y As Integer
Dim Field As Integer
Dim Channel As Integer
ActiveWorkbook.Sheets.Add
ActiveWorkbook.ActiveSheet.Cells.Select
range("A1").Select
For Field = 1 To 40
Channel = (Field - 1) / 10
Y = Field - 1
ActiveSheet.range("A1").Offset(Y, Channel).Value = Field
Next Field
End Sub
Y is the row to put the output in, which I usually set with
Y = (Field -1) mod 10
but I've left it as
Y = Field - 1
to illustrate the point more clearly in the resulting worksheet.
Channel is supposed to be the column that the output is put in.
When I run this macro, the values 1-6 get put in column A, then 7-15 get put into Column B, 16-26 get put into Column C, then 27-35 in Column D then 36-40 in Column E.
What I expected was that values 1-10 go into column A, 11-20 into column B, 21-30 into column C and 31-40 into column D.
I'm used to C and C++ where if I divide an integer by another integer, the result is calculated using integer maths. What's different in VBA?
To use "integer maths" for division use \ instead of /.
Integer Division \
Dividing an item means cutting it in pieces or fractions of a set
value. Therefore, the division is used to get the fraction of one
number in terms of another. The Visual Basic language provides two
types of operations for the division. If you want the result of the
operation to be a natural number, called an integer, use the backlash
operator "\" as the divisor. The formula to use is: Value1 \ Value2
This operation can be performed on two types of valid numbers, with or
without decimal parts. After the operation, the result would be a
natural number.
Decimal Division /
The second type of division results in a decimal
number. It is performed with the forward slash "/". Its formula is:
Value1 / Value2 After the operation is performed, the result is a
decimal number.
Source
The back slash is used for integer division, and the forward slash for decimal division. Change your forward slash to a back slash and you should get the result you are expecting.
http://www.functionx.com/vbaexcel/Lesson04.htm

Algorithm to form a given pattern using some strings

Given are 6 strings of any length. The words are to be arranged in the pattern shown below. They can be arranged either vertically or horizontally.
--------
| |
| |
| |
---------------
| |
| |
| |
--------
The pattern need not to be symmetric and there need to be two empty areas as shown.
For example:
Given strings
PQF
DCC
ACTF
CKTYCA
PGYVQP
DWTP
The pattern can be
DCC...
W.K...
T.T...
PGYVQP
..C..Q
..ACTF
where dot represent empty areas.
The other example is
RVE
LAPAHFUIK
BIRRE
KZGLPFQR
LLHU
UUZZSQHILWB
Pattern is
LLHU....
A..U....
P..Z....
A..Z....
H..S....
F..Q....
U..H....
I..I....
KZGLPFQR
...W...V
...BIRRE
If multiple patterns are possible then pattern with lexicographically smallest first line, then second line and so on is to be formed. What algorithm can be used to solve this?
Find strings which suits to this constraint:
strlen(a) + strlen(b) - 1 = strlen(c)
strlen(d) + strlen(e) - 1 = strlen(f)
After that try every possible situation if they are valid. For example;
aaa.....
d.f.....
d.f.....
d.f.....
cccccccc
..f....e
..f....e
..bbbbbb
There will be 2*2*2 = 8 different situation.
There are a number of heuristics that you can apply, but before that, let's go over some properties of the puzzle.
+aa+
c f
+ee+eee+
f d
+bbb+
Let us call the length of the string with the same character as appeared in the diagram above. We have:
a + b - 1 = e
c + d - 1 = f
I will refer to the 2 strings for the cross in the middle as middle strings.
We also infer that the length of the string cannot be less than 2. Therefore, we can infer:
e > a, e > b
f > c, f > d
From this, we know that the 2 shortest strings cannot be middle strings, due to the inequality above.
The 3 largest strings cannot be equal also, since after choosing any of 3 string as middle string, we are left with 2 largest strings that are equal, and it is impossible according to the inequality above.
The puzzle is only tricky when the lengths are regular. When the lengths are irregular, you can do direct mapping from length to position.
If we have the 2 largest strings being equal, due to the inequality above, they are the 2 middle strings. The worst case for this one is a "regular" puzzle, where the length a, b, c, d are equal.
If the 2 largest strings are unequal, the largest string's position can be determined immediately (since its length is unique in the puzzle) - as one of the middle string. In worst case, there can be 3 candidates for the other middle string - just brute force and check all of them.
Algorithm:
Try to map unique length string to the position.
Brute force the 2 strings in the middle (taken into consideration what I mentioned above), and brute force to fill in the rest.
Even with stupid brute force, there are only 6! = 720 cases, if the string can only go from left to right, up to down (no reverse). There will be 46080 cases (* 2^6) if the string is allowed to be in any direction.

Group digits in currency and remove leading zeroes

I want to know how to do
digit grouping
when I have value for money for example 3000000 ( 3million) i want to print 3.000.000 on the screen (there is a dot every three character from the last character)
Remove zeroes in front of value
when I select a value from table and print it on the screen, the value get padded with zeroes automatically: e.g. 129 becomes 0000129
The WRITE statement allows you to specify a currency. Example:
DATA price TYPE p DECIMALS 2.
price = '3000000'.
WRITE: / price CURRENCY 'USD'.
Note that this does not interpret the number itself, but just adds commas and dots at certain positions depending on the currency you specify. So in the event you have an integer with the value of 3000000 and you write it with currency USD the result will be 30.000,00.
I suggest you read the F1 help information on the WRITE statement, because there are a lot more options besides this one.
--
Removing leading zeroes is done by using a conversion routine.
The CONVERSION_EXIT_ALPHA_INPUT will add leading zeroes and CONVERSION_EXIT_ALPHA_OUTPUT will remove them.
It is possible to add these routines to a Domain in the dictionary, so the conversion will be done automatically. For example the MATNR type:
DATA matnr TYPE matnr.
matnr = '0000129'.
WRITE: / matnr.
This will output 129 because the Domain MATNR has a conversion routine specified.
In the case of a type which does not have this, for example:
DATA value(7) TYPE n.
value = '0000129'.
WRITE: / value.
The output will be 0000129. You can call the CONVERSION_EXIT_ALPHA_OUTPUT routine to achieve the output without leading zeroes:
DATA value(7) TYPE n.
value = '0000129'.
CALL FUNCTION 'CONVERSION_EXIT_ALPHA_OUTPUT'
EXPORTING
input = value
IMPORTING
output = value.
WRITE: / value.
Please also note that output conversion for numberlike types - triggered by the WRITE statement - is controlled by a property in the user master data.
Decimal separator and digit grouping should be configured there.
You could check this in the user master transactions e.g. SU01 or SU01D.
For removing the zero padding use NO-ZERO statement. For the thousand separator I do not see any problem because it is a standard way ABAP prints values of type P. Here is a sample code.
REPORT ZZZ.
DATA:
g_n TYPE n LENGTH 10 VALUE '129',
g_p TYPE p LENGTH 12 DECIMALS 2 VALUE '3000000'.
START-OF-SELECTION.
WRITE /: g_n, g_p.
WRITE /: g_n NO-ZERO, g_p.
This produces the output.
000000129
3.000.000,00
129
3.000.000,00
For removing leading zeros, you can do the following:
data: lv_n type n length 10 value '129'.
shift lv_n left deleting leading '0'.

Resources