Decimal to binary conversion for large numbers in Excel - excel

I have some large numbers in an Excel sheet and I want to convert them to binary.
e.g.
12345678
965321458
-12457896

If we are talking positive number between 0 and 2^32-1 you can use this formula:
=DEC2BIN(MOD(QUOTIENT($A$1,256^3),256),8)&DEC2BIN(MOD(QUOTIENT($A$1,256^2),256),8)&DEC2BIN(MOD(QUOTIENT($A$1,256^1),256),8)&DEC2BIN(MOD(QUOTIENT($A$1,256^0),256),8)
NOTE: =DEC2BIN() function cannot handle numbers larger than 511 so as you see my formula breaks your number into four 8-bit chunks, converts them to binary format and then concatenates the results.
Well, theoretically you can extend this formula up to six 8-bit chunks. Maximum precision you can get in Excel is 15 (fifteen) decimal digits. When exceeded, only the most significant 15 digits remain, the rest is rounded. I.e. if you type 12345678901234567 Excel will store it as 12345678901234500. So since 2^48-1 is 15 decimal digits long the number won't get rounded.

Perhaps a simpler option:
For positive numbers only, just use BASE (as in BASE2) for numbers between 0 to 2^53 in Excel. Here are some examples:
=BASE(3,2) # returns 11
=BASE(11,2) # returns 1011
Credit for answer goes here:
https://ask.libreoffice.org/en/question/69797/why-is-dec2bin-limited-to-82bits-in-an-32-and-64-bits-world/
Negative numbers: Come to think of it, negative numbers could be handled as well by building upon howy61's answer. He shifts everything by a power of two (2^31 in his case) to use the 2's complement:
=BASE(2^31+MyNum, 2)
so (using 2^8 for only 8 bits):
=BASE(2^8+(-1),2) # returns 11111111
=BASE(2^8+(-3),2) # returns 11111101
The numbers given by the OP requires more bits, so I'll use 2^31 (could go up to 2^53):
=BASE(2^31+(-12457896),2) # returns 11111111010000011110100001011000
For either positive or negative, both formulas could be coupled in a single IF formula. Here are two ways you could do it that give the same answer, where MyNum is the decimal number you start with:
=IF(MyNum<0, BASE(2^31+MyNum,2), BASE(MyNum, 2))
or
=BASE(IF(MyNum<0, MyNum+2^32, MyNum), 2)

See VBA posted here
' The DecimalIn argument is limited to 79228162514264337593543950245
' (approximately 96-bits) - large numerical values must be entered
' as a String value to prevent conversion to scientific notation. Then
' optional NumberOfBits allows you to zero-fill the front of smaller
' values in order to return values up to a desired bit level.
Function DecToBin(ByVal DecimalIn As Variant, Optional NumberOfBits As Variant) As String
DecToBin = ""
DecimalIn = CDec(DecimalIn)
Do While DecimalIn <> 0
DecToBin = Trim$(Str$(DecimalIn - 2 * Int(DecimalIn / 2))) & DecToBin
DecimalIn = Int(DecimalIn / 2)
Loop
If Not IsMissing(NumberOfBits) Then
If Len(DecToBin) > NumberOfBits Then
DecToBin = "Error - Number too large for bit size"
Else
DecToBin = Right$(String$(NumberOfBits, "0") & _
DecToBin, NumberOfBits)
End If
End If
End Function

I just tried the formula above, and found that Microsoft screwed up the DEC2BIN function in another way that keeps the formula from working correctly with negative numbers. Internally, DEC2BIN uses a ten bit result; leading zeroes are dropped from the text result, unless the optional length parameter is used, in which case the required number of leading zeroes are left in the string. But here's the rub: a negative number always starts with a one, so there are no leading zeroes to drop, so DEC2BIN will always show all ten bits! Thus, DEC2BIN(-1,8), which should show 11111111 (eight ones) will instead show 1111111111 (ten ones.)
To fix this, use RIGHT to trim each eight bit chunk to eight bits, dumb as that sounds.
=RIGHT(DEC2BIN(QUOTIENT(A1,256^3),8),8) & RIGHT(...
(I read through the VBA, and it does not have the same problem, but it doesn't look like it will handle negatives at all.)

To add easier to read formatting to Taosique's great answer, you can also break it up into chunks of 4 bits with spaces in between, although the formula grows to be a monster:
=DEC2BIN(MOD(QUOTIENT($A$1,16^7),16),4)&" "&DEC2BIN(MOD(QUOTIENT($A$1,16^6),16),4)&" "&DEC2BIN(MOD(QUOTIENT($A$1,16^5),16),4)&" "&DEC2BIN(MOD(QUOTIENT($A$1,16^4),16),4)&" "&DEC2BIN(MOD(QUOTIENT($A$1,16^3),16),4)&" "&DEC2BIN(MOD(QUOTIENT($A$1,16^2),16),4)&" "&DEC2BIN(MOD(QUOTIENT($A$1,16^1),16),4)&" "&DEC2BIN(MOD(QUOTIENT($A$1,16^0),16),4)
1101 0100 1111 0110 0011 0001 0000 0001
Of course, you can just use the right half of it, if you're just interested in 16 bit numbers:
=DEC2BIN(MOD(QUOTIENT($A$1,16^3),16),4)&" "&DEC2BIN(MOD(QUOTIENT($A$1,16^2),16),4)&" "&DEC2BIN(MOD(QUOTIENT($A$1,16^1),16),4)&" "&DEC2BIN(MOD(QUOTIENT($A$1,16^0),16),4)
0011 0001 0000 0001

While I didn't write this for negatives or decimals, it should be relatively easy to modify. This VBA will convert any super large (or not so large if you want, but that wasn't the point) decimal up to the converted binary result containing up to 32767 digits (maximum string length in VBA).
Enter decimal in cell "A1" as a string, result will be in "B1" as a string.
Dim NBN As String
Dim Bin As String
5 Big = Range("A1")
AA = Len(Big)
For XX = 1 To AA
L1 = Mid(Big, XX, 1) + CRY
CRY = 0
If L1 = 0 Then
FN = "0"
GoTo 10
End If
If Int(L1 / 2) = L1 / 2 Then
FN = L1 / 2
GoTo 10
End If
If Int(L1 / 2) <> L1 / 2 Then
FN = Int(L1 / 2)
CRY = 10
GoTo 10
End If
10 NBN = NBN & FN
Next XX
If Left(NBN, 1) = "0" Then
NBN = Right(NBN, (Len(NBN) - 1))
End If
If CRY = 10 Then Bin = "1" & Bin Else Bin = "0" & Bin
Range("A1") = NBN
Range("A2") = Bin
If Len(NBN) > 0 Then
NBN = ""
CRY = 0
GoTo 5
End If

Someone can find binary shift operations more clear and relevant here
=DEC2BIN(BITRSHIFT($A$1,24),8) & DEC2BIN(MOD(BITRSHIFT($A$1,16),256),8) & DEC2BIN(MOD(BITRSHIFT($A$1,8),256),8) & DEC2BIN(MOD($A$1,256),8)
This formula is for 32-bit values

This vba function solves the problem of binary conversion of numbers greater than 511 that can not be done with WorksheetFunction.dec2bin.
The code takes advantage of the WorksheetFunction.dec2bin function by applying it in pieces.
Function decimal2binary(ByVal decimal2convert As Long) As String
Dim rest As Long
If decimal2convert = 0 Then
decimal2binary = "0"
Exit Function
End If
Do While decimal2convert > 0
rest = decimal2convert Mod 512
decimal2binary = Right("000000000" + WorksheetFunction.Dec2Bin(rest), 9) + decimal2binary
decimal2convert = (decimal2convert - rest) / 512
Loop
decimal2binary = Abs(decimal2binary)
End Function

=IF(Decimal>-1,BASE(Decimal,2,32),BASE(2^32+(Decimal),2))
Does both positive and negative numbers.
Took a bit LOL. Tech pun.
You're welcome.

Here's another way. It's not with a single formula, but I have tried and converted up to the number 2,099,999,999,999. My first intention was to build a 51 bit counter, but somehow it does not work with numbers beyond the one I mentioned. Download from
http://www.excelexperto.com/content/macros-production/contador-binario-de-51-bits/
I hope it's useful. Regards.

Without VBA and working with negative numbers as well (here: sint16), however, taking much more space:
You can download the excel file here: (sorry, didn't know where to put the file)
int16 bits to decimal.xlsx
or alternatively follow these steps (if your Excel is not in English, use Excel Translator to "translate" the formula into your MS Office language):
Enter the binary number in 4-bit nibbles (A4 = most significant to D4 = least significant) like shown in the screenshot. Enter all 4 digits (even if starting with 0) and format them as "text"
Enter formula in F4:
=IF(NUMBERVALUE(A4)>=1000,TRUE,FALSE)
Enter the letter "A" in G2-J2, "B" in K2-N2, "C" in O2-R2, "D" in S2-V2
Enter "1" in G3, K3, O3 and S3; "2" in H3, L3, P3 and T3; "3" in I3, M3, Q3 and U3; "4" in J3, N3, R3 and V3
In G4, enter:
=MID(INDIRECT(G$2&ROW()),G$3,1)
Copy the formula to H4-V4
In X4, enter:
=IF(G4="1",0,1)
Copy X4 to Y4-AM4
In BD3 enter "1"
In BC4, enter:
=IF((AM$4+BD3)=2,1,0)
IN BD4, enter:
=IF((AM$4+BD3)=2,0,IF((AM$4+BD3)=1,1,0))
Copy BD4 and BD4 and insert it 15 times diagonally one row further down and one column further left (like in the screenshot), i.e. insert it to BB5 and BC5, then BA6 and BB6, ..., AN19 and AO19.
In AO20, enter "=AO19"; in AP20, enter "=AP18" and so on until BD20 ("=BD4") - i.e. bring down the numbers into one line as seen in the screenshot
In BE20, enter (this is your result):
=IF(F4=FALSE,BIN2DEC(A4&B4)*2^8+BIN2DEC(C4&D4),-1*(BIN2DEC(AO20&AP20&AQ20&AR20&AS20&AT20&AU20&AV20)*2^8+BIN2DEC(AW20&AX20&AY20&AZ20&BA20&BB20&BC20&BD20)))

There maybe a simple solution. I have several 4.2 billion cells that are actually a negative Two's Complement and this works to get the correct value:
=SUM(2^31-(A1-2^31))

Related

Excel - Deleting zeros on the right side of the cells

I would like to delete the zeros on the right side of the cells if there are more then 3 zeros.
Example:
A B
12345 12345
1230 1230
12345600 12345600
12000 12000
12340000000000000 1234000
1234500000000000000000 12345000
Is it possible to excel using just formula in the cells of the column B??
How to do?
Thanks so much!
The answers, given until now, are treating the numbers as strings, while I'd go for the numeric approach:
if mod(number,10000) = 0
then number = number div 1000;
return number;
Which means: if the number, divided by 10,000 equals 0 (if the number ends with '0000') then return the number, divided by a thousand (remove the last three zeroes).
You don't need this one time, but you need to remove all triplets of three zeroes, as much as possible, so instead of a simple if-loop, you might go for a while-loop:
while mod(number,10000) = 0
do number = number div 1000;
return number;
You can use this in a VBA function:
Public Function remove_ending_blanks(r As Range) As Double
Dim temp As Double
temp = r.Value
While temp Mod 10000 = 0
temp = temp / 1000
Wend
remove_ending_blanks = temp
End Function
You might also do this, using a formula, but the while-loop will need to be done using a circular reference, which is quite tricky.
Try this shorter formula solution and worked in left max. 3 zeros on the right side.
In B1, formula copied down :
=0+TRIM(LEFT(A1,MATCH(9^9,INDEX(1/MID(A1,ROW($1:$99),1),0))+3))
Bit of a stretch (I'm prety sure it can be done better), but if you have access to TEXTJOIN, try the following in B2:
=IF(RIGHT(A1,4)="0000",FILTERXML("<t><s>"&TEXTJOIN("</s><s>",1,MID(A1,1,LEN(A1)-ROW(A$1:INDEX(A:A,LEN(A1)))))&"</s></t>","//s[substring(., string-length(.)-3) != 0]"),A1)
Or:
=IF(RIGHT(A7,4)="0000",LEFT(A7,MAX((MID(A7,ROW(A$1:INDEX(A:A,LEN(A7))),1)<>"0")*(ROW(A$1:INDEX(A:A,LEN(A7)))))+3),A7)
Note: It's an array formula and needs to be confirmed through CtrlShiftEnter
It looks frightening, agreed, but would yield the correct result as far as my testing went. For example 100000400000 would yield 1000004000.
you could use this formula
=IF(RIGHT(A1,4)="0000",LEFT(A1,LEN(A1/10^LEN(A1))-FIND(".",A1/10^LEN(A1))+3),A1)
Consider:
Public Function ZeroTrimmer(r As Range) As String
s = r.Text
While Right(s, 4) = "0000"
s = Left(s, Len(s) - 1)
Wend
ZeroTrimmer = s
End Function
Edit: These will give incorrect results. I mis-read the question and didn't realize you wanted to leave a max of 3 trailing zeroes. The below will remove all trailing zeroes.
If it's an unknown number of trailing zeroes, it gets tricky. You'd have to use something like this...
=(10^(LEN(RIGHT(VALUE(CONCATENATE("0.", A2)),LEN(VALUE(CONCATENATE("0.", A2)))-FIND(".",VALUE(CONCATENATE("0.", A2)))))))*VALUE(CONCATENATE("0.", A2))
If you know the number of trailing zeroes it becomes much easier, and can be done like this:
=LEFT(A2,LEN(A2)-3)
Where 3 in the above formula represents the number of trailing zeroes to remove. Another variation could be:
=A2/(10^3)
These formulas will work if text or numeric.

How to get excel to display a certain number of significant figures?

I am using excel and i want to display a value to a certain number of significant figures.
I tried using the following equation
=ROUND(value,sigfigs-1-INT(LOG10(ABS(value))))
with value replaced by the number I am using and sigfigs replaced with the number of significant figures I want.
This formula works sometimes, but other times it doesn't.
For instance, the value 18.036, will change to 18, which has 2 significant figures. The way around this is to change the source formatting to retain 1 decimal place. But that can introduce an extra significant figure. For instance, if the result was 182 and then the decimal place made it change to 182.0, now I would have 4 sig figs instead of 3.
How do I get excel to set the number of sig figs for me so I don't have to figure it out manually?
The formula (A2 contains the value and B2 sigfigs)
=ROUND(A2/10^(INT(LOG10(A2))+1),B2)*10^(INT(LOG10(A2))+1)
may give you the number you want, say, in C2. But if the last digit is zero, then it will not be shown with a General format. You have then to apply a number format specific for that combination (value,sigfigs), and that is via VBA. The following should work. You have to pass three parameters (val,sigd,trg), trg is the target cell to format, where you already have the number you want.
Sub fmt(val As Range, sigd As Range, trg As Range)
Dim fmtstr As String, fmtstrfrac As String
Dim nint As Integer, nfrac As Integer
nint = Int(Log(val) / Log(10)) + 1
nfrac = sigd - nint
If (sigd - nint) > 0 Then
'fmtstrfrac = "." & WorksheetFunction.Rept("0", nfrac)
fmtstrfrac = "." & String(nfrac, "0")
Else
fmtstrfrac = ""
End If
'fmtstr = WorksheetFunction.Rept("0", nint) & fmtstrfrac
fmtstr = String(nint, "0") & fmtstrfrac
trg.NumberFormat = fmtstr
End Sub
If you don't mind having a string instead of a number, then you can get the format string (in, say, D2) as
=REPT("0",INT(LOG10(A2))+1)&IF(B2-(INT(LOG10(A2))+1)>0,"."&REPT("0",B2-(INT(LOG10(A2))+1)),"")
(this replicates the VBA code) and then use (in, say, E2)
=TEXT(C2,D2).
where cell C2 still has the formula above. You may use cell E2 for visualization purposes, and the number obtained in C2 for other math, if needed.
WARNING: crazy-long excel formula ahead
I was also looking to work with significant figures and I was unable to use VBA as the spreadsheets can't support them. I went to this question/answer and many other sites but all the answers don't seem to deal with all numbers all the time. I was interested in the accepted answer and it got close but as soon as my numbers were < 0.1 I got a #value! error. I'm sure I could have fixed it but I was already down a path and just pressed on.
Problem:
I needed to report a variable number of significant figures in positive and negative mode with numbers from 10^-5 to 10^5. Also, according to the client (and to purple math), if a value of 100 was supplied and was accurate to +/- 1 and we wish to present with 3 sig figs the answer should be '100.' so I included that as well.
Solution:
My solution is for an excel formula that returns the text value with required significant figures for positive and negative numbers.
It's long, but appears to generate the correct results according to my testing (outlined below) regardless of number and significant figures requested. I'm sure it can be simplified but that isn't currently in scope. If anyone wants to suggest a simplification, please leave me a comment!
=TEXT(IF(A1<0,"-","")&LEFT(TEXT(ABS(A1),"0."&REPT("0",sigfigs-1)&"E+00"),sigfigs+1)*10^FLOOR(LOG10(TEXT(ABS(A1),"0."&REPT("0",sigfigs-1)&"E+00")),1),(""&(IF(OR(AND(FLOOR(LOG10(TEXT(ABS(A1),"0."&REPT("0",sigfigs-1)&"E+00")),1)+1=sigfigs,RIGHT(LEFT(TEXT(ABS(A1),"0."&REPT("0",sigfigs-1)&"E+00"),sigfigs+1)*10^FLOOR(LOG10(TEXT(ABS(A1),"0."&REPT("0",sigfigs-1)&"E+00")),1),1)="0"),LOG10(TEXT(ABS(A1),"0."&REPT("0",sigfigs-1)&"E+00"))<=sigfigs-1),"0.","#")&REPT("0",IF(sigfigs-1-(FLOOR(LOG10(TEXT(ABS(A1),"0."&REPT("0",sigfigs-1)&"E+00")),1))>0,sigfigs-1-(FLOOR(LOG10(TEXT(ABS(A1),"0."&REPT("0",sigfigs-1)&"E+00")),1)),0)))))
Note: I have a named range called "sigfigs" and my numbers start in cell A1
Test Results:
I've tested it against the wikipedia list of examples and my own examples so far in positive and negative. I've also tested with a few values that gave me issues early on and all seem to produce the correct results.
I've also tested with a few values that gave me issues early on and all seem to produce the correct results now.
3 Sig Figs Test
99.99 -> 100.
99.9 -> 99.9
100 -> 100.
101 -> 101
Notes:
Treating Negative Numbers
To Treat Negative Numbers, I have included a concatenation with a negative sign if less than 0 and use the absolute value for all other work.
Method of construction:
It was initially divided into about 6 columns in excel that performed the various steps and at the end I merged all of the steps into one formula above.
Use scientific notation, say if you have 180000 and you need 4 sigfigs the only way is to type as 1.800x10^5
I added to your formula so it also automatically displays the correct number of decimal places. In the formula below, replace the digit "2" with the number of decimal places that you want, which means you would need to make four replacements. Here is the updated formula:
=TEXT(ROUND(A1,2-1-INT(LOG10(ABS(A1)))),"0"&IF(INT(LOG10(ABS(ROUND(A1,2-1-INT(LOG10(ABS(A1)))))))<1,"."&REPT("0",2-1-INT(LOG10(ABS(ROUND(A1,2-1-INT(LOG10(ABS(A1)))))))),""))
For example, if cell A1 had the value =1/3000, which is 0.000333333.., the above formula as-written outputs 0.00033.
This is an old question, but I've modified sancho.s' VBA code so that it's a function that takes two arguments: 1) the number you want to display with appropriate sig figs (val), and 2) the number of sig figs (sigd). You can save this as an add-in function in excel for use as a normal function:
Public Function sigFig(val As Range, sigd As Range)
Dim nint As Integer
Dim nfrac As Integer
Dim raisedPower As Double
Dim roundVal As Double
Dim fmtstr As String
Dim fmtstrfrac As String
nint = Int(Log(val) / Log(10)) + 1
nfrac = sigd - nint
raisedPower = 10 ^ (nint)
roundVal = Round(val / raisedPower, sigd) * raisedPower
If (sigd - nint) > 0 Then
fmtstrfrac = "." & String(nfrac, "0")
Else
fmtstrfrac = ""
End If
If nint <= 0 Then
fmtstr = String(1, "0") & fmtstrfrac
Else
fmtstr = String(nint, "0") & fmtstrfrac
End If
sigFig = Format(roundVal, fmtstr)
End Function
It seems to work in all the use cases I've tried so far.
Rounding to significant digits is one thing... addressed above. Formatting to a specific number of digits is another... and I'll post it here for those of you trying to do what I was and ended up here (as I will likely do again in the future)...
Example to display four digits:
.
Use Home > Styles > Conditional Formatting
New Rule > Format only cells that contain
Cell Value > between > -10 > 10 > Format Number 3 decimal places
New Rule > Format only cells that contain
Cell Value > between > -100 > 100 > Format Number 2 decimal places
New Rule > Format only cells that contain
Cell Value > between > -1000 > 1000 > Format Number 1 decimal place
New Rule > Format only cells that contain
Cell Value > not between > -1000 > 1000 > Format Number 0 decimal places
.
Be sure these are in this order and check all of the "Stop If True" boxes.
The formula below works fine. The number of significant figures is set in the first text formula. 0.00 and 4 for 3sf, 0.0 and 3 for 2sf, 0.0000 and 6 for 5sf, etc.
=(LEFT((TEXT(A1,"0.00E+000")),4))*POWER(10,
(RIGHT((TEXT(A1,"0.00E+000")),4)))
The formula is valid for E+/-999, if you have a number beyond this increase the number of the last three zeros, and change the second 4 to the number of zeros +1.
Note that the values displayed are rounded to the significant figures, and should by used for display/output only. If you are doing further calcs, use the original value in A1 to avoid propagating minor errors.
As a very simple display measure, without having to use the rounding function, you can simply change the format of the number and remove 3 significant figures by adding a decimal point after the number.
I.e. #,###. would show the numbers in thousands. #,###.. shows the numbers in millions.
Hope this helps
You could try custom formatting instead.
Here's a crash course: https://support.office.com/en-nz/article/Create-a-custom-number-format-78f2a361-936b-4c03-8772-09fab54be7f4?ui=en-US&rs=en-NZ&ad=NZ.
For three significant figures, I type this in the custom type box:
[>100]##.0;[<=100]#,##0
You could try
=ROUND(value,sigfigs-(1+INT(LOG10(ABS(value)))))
value :: The number you wish to round.
sigfigs :: The number of significant figures you want to round to.

How to build complex value from three variables?

I have an Excel spreadsheet with over 2000 entries:
Field B1: CustomerID as 000012345
Field B2: CustomerID as 0000432
Field C1: CustomerCountry as DE
Field C2: CustomerCountry as IT
I need to build codes 13 digits long including "CustomerCountry" + "CustomerID" without leading 0 + random number (can be 6 digits, more or less, depends in length of CustomerID).
The results should be like this: D1 Code as DE12345967895 or D2 Code as IT43274837401
How to do it with Excel functions?
UPDATED:
I tried this one. My big problem is to say that random number should be long enough to get 13 characters in all. Sometimes CustomerID is just 3 or 4 digits long, and concatenation of three variables can be just 10 or 9 characters. But codes have to be always 13 characters long.
Use & to concatenate strings.
Use VALUE(CustomerID) to trim the leading zeroes from the ID
Use RAND() to add a random number between 0 and 1 or RANDBETWEEN(x,y) to create one between x and y.
Combine the above and there you are!
If you always want 13 digits you can use LEFT(INT(RAND()*10^13);(13-LEN(CustomerCountry)-LEN(VALUE(CustomerID)))) for the random number to ALWAYS be the right length.
total formula
= CustomerCountry
& VALUE(CustomerID)
& LEFT(INT(RAND()*10^13);(13-LEN(CustomerCountry)-LEN(VALUE(CustomerID))))
=C1 & TEXT(B1,"0") & RIGHT(TEXT(RANDBETWEEN(0,99999999999),"00000000000"),11 - LEN(TEXT(B1,"0")))
that should do it
I don’t understand what is where and OP has accepted answer so have not bothered testing:
=LEFT(RIGHT(C1,2)&VALUE(MID(B1,15,13))&RANDBETWEEN(10^9,10^10),13)
(but I might revert to this if no one else picks the flaws in it first!)

SI-prefixes for number format in MS Excel

Does anybody know if it is possible to show numbers in MS Excel with SI-prefixes?
I'd like to have
... 1 n, 1 µ, 1 m, 1, 1 k, 1M, 1 G, ...
instead of scientific format
... 1E-09, 1E-06, 1E-03, 1, 1E+03, 1E+06. 1E+09, ...
Perhaps adding an unit like V (volts), F (farad) etc.
I would be perfect, if the cell would still contain the number and not a string, so it can easily be changed to another format (back to scientific or whatever)
You can do something like this, which I got from Millions & Thousands Custom Number Formatting :
[>=1000000] #,##0.0,," MΩ";[<1000000] #,##0.0," kΩ";General
400 renders as 0.4 kΩ (probably not what you want)
4000 renders as 4.0 kΩ
40e3 renders as 40.0 kΩ
40e6 renders as 40.0 MΩ
but you can probably add more clauses to cover other ranges. Nevermind, you can't.
You can also use LOG and CHOOSE to keep it in a single formula and reasonably compact.
=ROUND(
E10 / (1000 ^ INT(LOG(ABS(E10),1000)) )
,0
) & CHOOSE(
INT(LOG(ABS(E10),1000)) + 6
,"f","p","n","µ","m","","k","M","G","T","P"
)
In this formula:
E10 (referred to 3 times) is the cell containing the raw value.
ROUND formats number for display, here rounding to no decimals (0).
INT(LOG(ABS(E10),1000)) is the prefix index -5 through +5.
CHOOSE is the prefix to use (needs positive index, hence + 6).
No solution will work better than scientific notation.
If you use custom number formats, then you would have to enter them manually (or with VBA) such that they will mask the actual content of the cell.
For instance, if you want to display the following format pairs:
1 n 1E-09
1 µ 1E-06
1 m 1E-03
1 1
1 k 1E+03
1 M 1E+06
1 G 1E+09
If you have 0.001, you would have to set the format as "1 m" -- this will mask the number, so if you have 0.002 you would have to set it as "2 m" -- if you changed it to 0.004 it would still display 2 m as a result. This obviously isn't ideal.
You could set it up as a two-column sheet, where you have the values in the left, and use a formula to display with units on the right, but then you end up not being able to do math with the formatted values.
So basically, the answer is "no", it isn't possible.
You could theoretically write a VBA script that will automatically change the visible contents according to the cell contents whenever a number is changed, but the script would be bulky and would cause serious trouble to whoever you sent to if they had macros off. It would also require all sorts of corner cases depending on if you wanted numbers formatted 'normally' in certain cells. So while it may be theoretically possible, it is practically impossible
It is possible, though bulky using a conversion table and the match and index functions.
From a conversion table like this (2 columns):
1.E+15 P
1.E+12 T
1.E+09 G
1.E+06 M
1.E+03 k
1.E+00
1.E-03 m
1.E-06 µ
1.E-09 n
1.E-12 p
1.E-15 f
You could then perform the following translation
3.68437E+11 --> 368.44 G
If you have the conversion table in columns A and B
and the unformatted number in cell G1
H1
=G1/INDEX(A:A,MATCH(G1,$A:$A,-1)+1)
I1
=INDEX($B:$B,MATCH(G1,$A:$A,-1)+1)
Then the proper numerals will display in column H with the suffix/prefix in column I.
It is still ponderous, and should only be used for final output since calculations from the modified numbers will have to include a reverse translation.
There's no way I know of to do this as a number format (where you can then use the formatted number as you would any other numeric value for subsequent calculation), but for simply presenting the number using SI prefixes, here's the formula I use. It takes the formula in the specified cell (usually next to it, in this case E28), scales the number, rounds to the specified number of significant figures (in this case 3), appends the appropriate SI prefix, and then appends the specified unit (in this case 'F' for Farads). The advantage here is that the formula is self-contained and doesn't require any external reference tables. This formula works for femto (10^-15) through Tera (10^12), but can easily be expanded for additional prefixes
=CONCAT(
ROUND(
IF(E28>1E12, E28/1E12,
IF(E28>1E9, E28/1E9,
IF(E28>1E6, E28/1E6,
IF(E28>1E3, E28/1E3,
IF(E28>1, E28,
IF(E28>1E-3, E28*1E3,
IF(E28>1E-6, E28*1E6,
IF(E28>1E-9, E28*1E9,
IF(E28>1E-12, E28*1E12,
E28*1E15
) ) ) ) ) ) ) ) ),
3 +N("This is the number of significant digits to round to")
-(1+INT(LOG10(ABS(
IF(E28>1E12, E28/1E12,
IF(E28>1E9, E28/1E9,
IF(E28>1E6, E28/1E6,
IF(E28>1E3, E28/1E3,
IF(E28>1, E28,
IF(E28>1E-3, E28*1E3,
IF(E28>1E-6, E28*1E6,
IF(E28>1E-9, E28*1E9,
IF(E28>1E-12, E28*1E12,
E28*1E15
) ) ) ) ) ) ) ) ) ))))
),
IF(E28>1E12, "T",
IF(E28>1E9, "G",
IF(E28>1E6, "M",
IF(E28>1E3, "k",
IF(E28>1, "",
IF(E28>1E-3, "m",
IF(E28>1E-6, "µ",
IF(E28>1E-9, "n",
IF(E28>1E-12, "p",
"f"
) ) ) ) ) ) ) ) ),
"F" +N("This is the unit symbol that will be appended to the end")
)
If you want to round to a fixed number of decimal figures as opposed to significant figures, the formula is a little simpler:
=CONCAT(
ROUND(
IF(E28>1E12, E28/1E12,
IF(E28>1E9, E28/1E9,
IF(E28>1E6, E28/1E6,
IF(E28>1E3, E28/1E3,
IF(E28>1, E28,
IF(E28>1E-3, E28*1E3,
IF(E28>1E-6, E28*1E6,
IF(E28>1E-9, E28*1E9,
IF(E28>1E-12, E28*1E12,
E28*1E15
) ) ) ) ) ) ) ) ),
3 +N("This is the number of decimal digits to round to")
),
IF(E28>1E12, "T",
IF(E28>1E9, "G",
IF(E28>1E6, "M",
IF(E28>1E3, "k",
IF(E28>1, "",
IF(E28>1E-3, "m",
IF(E28>1E-6, "µ",
IF(E28>1E-9, "n",
IF(E28>1E-12, "p",
"f"
) ) ) ) ) ) ) ) ),
"F" +N("This is the unit symbol that will be appended to the end")
)
Note that I've written all of the scaling constants in exponential notation, Excel will change these to plain numbers when you enter the formula. By using a relative cell reference, it's pretty easy to copy and paste the formula around where you need it.
The formula could be condensed into a single block of IF/CONCAT/ROUND statements, but arranging it as I've done here separates out the rounding constant into a single point in the formula, making it easier to change.
Just select the cell or range of cells you want to contain the given symbol. Right click on the cell and select FORMAT CELLS. Select the NUMBER format on the left, enter decimal places, etc on the right. Now go all the way down the list of your format options on the left and select CUSTOM. (IMPORTANT: Do NOT select ANY custom format options on the right.) Left click in the box just below TYPE: and above the list of custom format options. (This box displays your current selected format. {0.00 if you selected the default number format} You want to keep this formatting AND add additional formatting.) Click to the right of 0.00 and type the following: " μ" Click OKAY and you may enter your data as normal. Formatting cells has no impact on the values you enter. You can perform all functions as normal. I am attaching a pic where I used the same instructions to apply litters and the greek MU notation to values and performed some basic calculations without impeding Excel's ability to function.Special Notation in Excel
This is a limited answer for Google Sheets, using actual number formats instead of expressions that output text.
Spinning off from endolith's answer, I settled on this:
[>=1E6] #,##0.0,,"M";[>1E3] #,##0.0,"K";0.#####################
It works on numbers from 1 to <1E16, though can't be expanded to units above M. Doesn't work for negative numbers or fractional numbers. It is limited by the number of conditional sections Google Sheets is able to parse.
Docs: https://developers.google.com/sheets/api/guides/formats#number_format_patterns
' Hans Wolfgang Schulze 20190921, cause I always need this and need to write it again cause I forgot where I saved it.
' Paste this into Excel's Macro Editor (F11) and use from any cell.
' Copyleft 2019. Please include original author's name in all derivative works.
'
' Note that the conversions in this code is assuming normal Base 10, and not Binary 1024. Lots of code has to change.
' Currently recognizes numbers like "-123123.123G" or "123E15" with or without actual units.
' Special case of Excel's "-" nothing equals 0.
' Assumes, if exists, that the rightmost character is the SI exponent designation - See expS below.
' Usage: =DSci("45e9k") gives "4.5E12" as an answer.
Const expS = "-qryzafpnum KMGTPEZYRQ" ' https://en.wikipedia.org/wiki/Metric_prefix
Function DSci(inputS As String) As Double
Dim which As Integer
which = InStr(expS, Right(inputS, 1))
whichUnitary = InStr(expS, " ") ' offset into expS for " " unity value
If which = 0 Then
which = InStr("----F-Nµ- k-gt-e", Right(inputS, 1)) ' try alt case and form that aren't obscure ie k=K or m!=M
End If
If which > 0 Then ' has a terminating exponential character. 1 is not found.
If which = 1 Then ' "-"
DSci = 0 ' excel nothing value (0)
Else ' convert only the left side of input
DSci = CDbl(Left(inputS, Len(inputS) - 1)) * 10# ^ ((which - whichUnitary) * 3#) ' fix for Binary K's
End If
Else
DSci = CDbl(inputS) ' convert whole string instead ' special case devide by 1.024 for each 1000 for Binary K's
End If
End Function
' Formats to SI convention 10 ^ (-30 ... +30) and recent suggested expansions
' Usage =Sci(5.531e9, "B") gives string of "5.531GB"
' Significant digits are suggested as 4, can be any positive number.
Function Sci(value As Double, optionalUnit As String, Optional significant As Integer = 4) As String
Dim mant As Double, exp As Double, rank As Integer
rankUnitary = InStr(expS, " ") ' offset into expS for " " unity value
If value = 0 Then exp = 0 Else exp = Log(value) / Log(10#) ' nDigits
mant = value / (10# ^ exp) '
While mant >= 999.9999999999 ' don't want 2000K, rather 2M. Change to 1023.9999999999# for Binary K's
exp = exp + 3#
mant = mant / 1000# ' change to 1024# for binary K's etc.
Wend
rank = Int((exp + 0.0000000000001) / 3#) ' should be >1E-300 or so? Why not? 3 != 3#? More changes for Binary K's ?
mant = mant * 10# ^ (-rank * 3# + exp) ' adjust mantussa after de-ranking. Change?? for Binary K's
If Abs(rank) >= rankUnitary Then ' outside of +/- yY bounds
expChar = "?" ' what do you call it then? Not defined.
Else
expChar = Mid(expS, rank + rankUnitary, 1) ' add SI
End If
Sci = Left(mant, Abs(significant)) ' don't allow negative numbers, pretend they are positive lengths
If Right(Sci, 1) = "." Then Sci = Left(Sci, Len(Sci) - 1) ' lop off right DP
Sci = Sci & " " & expChar & optionalUnit
End Function

How do I keep all the leading zeros on a Hexadecimal Range in VBA?

I am trying to expand a range of Hexadecimal numbers. For example I have on column K ... 1880 and column L ...188A my range is 1880-188A When I expand the Range, starting On column M I get 1880 1881 1882 1883 1884 1885 1886 etc etc.
From one of the posting I copied and changed the VBA script to fit my case... and it works ... but found 2 issues. All my device range are 4 digit and I need to keep all leading zeros.
For example if my range is 0000 - 0005 .... it errors... will not work.
If my range is 0001 - 0005 then I get 1 2 3 4 5.... and I want to be 0001 0002 0003 0004 0005
Any help will be much appreciated..
Thanks, JCam
Here is the script that I use it ... as long as there are no leading zeros on my range
Sub FillHexNumbers()
Dim cellKValue As Long
Dim cellLValue As Long
Dim diffBetweenKAndL As Long
Dim iCtr As Long
cellKValue = CLng(Format("&h" & Cells(2, 11).Text, "###"))
cellLValue = CLng(Format("&h" & Cells(2, 12).Text, "###"))
diffBetweenKAndL = cellLValue - cellKValue
For iCtr = 0 To diffBetweenKAndL
Cells(2, 13 + iCtr).Value = Hex(cellKValue + iCtr)
Next
End Sub
The Analysis Toolpak contains functions to convert between DEC and HEX - for HEX you can specify the # of digits, e.g. =DEC2HEX(14,4) gives "000E". You may enable this package by "Tools/Add-Ins...". By adding columns containing DEC numbers and displaying the HEX aequivalent you can maybe solve your task without VBA at all ...
Hope that helps
Try this:
Dim i as Integer 'This is the number you want to format
Dim l as Integer 'The length you want your format in (suppose it's six)
Dim h as String
l = 6
i = 47 'Any integer between 0 and 16,777,215
h = Replace(Space(l - len(hex(i))), " ", "0") & hex(i) 'h = "00002F"
The variable h will return the format text "00002F".
Cheers,
Rick.
you have to format the data as a string. You can do this with a single quite ie '0045.
may be something like this:
Cells(2, 13 + iCtr).Value = "'" & Hex(cellKValue + iCtr)
If you format a cell as text, then add your hex value with leading zeroes, they should remain.
If you are dealing with hex values that have already lost their leading zeroes, you can manually fix them in a text editor, then format your new cells as text, and paste values.
Alternatively, you can define a custom number format for those cells by right-clicking on them, choosing Format Cells..., choose Custom, then enter a value like "0000" (if, say, you'd like padding to four chars). This will only affect hex values that don't have an alpha character. If you enter 000A, Excel should preserve the zeroes and treat it as a string automatically.
It's very important that you also correct the cell formatting because Excel will remove the leading zeros if the format is General or Number. Two ways to correct this are:
Prefix your value with a single quote ( ' )
Cells(2, 13 + iCtr).Value = "'" & ...
Enforce a specific format.
Cells(2, 13 + iCtr).NumberFormat = "#" ' Text format
As for the challenge of adding the leading 0's. I've got three solutions for you.
Set the number format such that it displays the leading 0's. Note that this may not be the ideal solution if you really need the stored value to include the leading 0's.
Cells(2, 13 + iCtr).NumberFormat = "000000"
Use a binary Or with the value &H10000000 and then use Mid() or Right() to get rid of the leading 1. This has the disadvantage that your number can't be more than 7 digits in hex. However, given that the maximum column number in Excel 2016 is 16,384 (4 digits in hex) and the maximum row is 1,048,576 (6 digits in hex). That's kind of a non-issue.
' Using Mid()
Cells(2, 13 + iCtr).Value = Mid(Hex(&H10000000 Or (cellKValue + iCtr)), 2)
' Desired # of digits = # of 0's ^^^^^^^
' Using Right()
Cells(2, 13 + iCtr).Value = Right(Hex(&H10000000 Or (cellKValue + iCtr)), 4)
' Desired # of digits ^
Use the String() and Len() functions to pad the value with 0's. This has the disadvantage you must convert the number to hex twice, or create another variable to hold the converted string.
Cells(2, 13 + iCtr).Value = String(5 - Len(Hex(cellKValue + iCtr)), "0") & Hex(cellKValue + iCtr)
' Desired # of digits ^
Personally, I prefer the Or and Mid() method. It will ensure your raw value includes the leading 0's and it has the least number of functions/operations (thus it will perform the fastest).

Resources