C# Negative IP Address to dotted decimal using intel standards conversion - c#-4.0

I would like to have some help on this since I've been spending hours to do it, but I couldn't. I want to write a function that takes signed integer and convert it to a dotted IP address using Intel standard algorithm, here is an example:
the IP address 192.168.18.188 displays as -1139627840. To convert this IP address using Intel standards, I will have to perform the following procedure:
Convert (-1139627840) to a hex value. BC12A8C0.
Reverse the hex bytes, as shown below: CO A8 12 BC
Convert the bytes from hex to decimal, as shown below: 192 168 18 188
The IP address displays in the following format: 192.168.18.188
Any help would be appreciated.

I know this doesn't answer your question in regards to the Intel Standard, but just to throw it out there (in case you're trying to reinvent the wheel), you can convert an int to an IP like this:
string ip = new IPAddress(BitConverter.GetBytes(-1139627840)).ToString();

The magic is in combining:
the >> operator, which shifts the bits in a number to the right
the & operator, which does a bit-wise and (the more common && does a logical and)
So something like this:
var number = -1139627840;
var b1 = number & 255;
var b2 = (number >> 8) & 255;
var b3 = (number >> 16) & 255;
var b4 = (number >> 24) & 255;
Console.WriteLine(string.Format("{0}.{1}.{2}.{3}", b1, b2, b3, b4));

Related

MINICOM TTY communication and HEX conversion

I'm trying to send information through minicom to a device through TTY.
The interesting thing is that when I enter let's say "a" I see "4f", which in ASCII should be "61" hex, or "97" decimal. Other examples are:
b = 27
c = ce
1 = 67
2 = 33
3 = e6
They definitely do not correspond to their ASCII counterparts.
Obviously I am doing something wrong. I wonder - is there a way to figure the "formula" for translating the characters to hex.
Please help!

Excel: How to convert a decimal number into a 3 Byte binary

Consider the decimal number 10093264. I want to convert this number into a 3 Byte binary number and show the value of each byte as decimal. I.e. I want to rewrite the aforementioned number as:
154 2 208
So, what would be a possible way to achieve this?
I was thinking DEC2BIN to give me the binary number. But here is the problem: This function allows only inputs of up to 8 bits! My math is not the best, so maybe s.o. can help me out: What do I need to divide by what?
I realized, for example, that QUOTIENT(10093264;2^16) gives 154, which is my LSB. But I cannot apply the same method to give me the other bytes.
Use BITAND (Bitwise And), and Integer division or BITRSHIFT (Bitwise Right Shift)
So, the smallest byte (208) will just be =BITAND(10093264,255) - this will give you the last 8 bits:
100110100000001011010000 : 10093264
& 000000000000000011111111 : 255
= 000000000000000011010000 : 208
For the next smallest byte (2), you can start by either Integer Division (INT(10093264/256)) or BITRSHIFT (BITRSHIFT(10093264, 8)), then use BITAND on that again:
100110100000001011010000 : 10093264
→ 000000001001101000000010 : 39426
& 000000000000000011111111 : 255
= 000000000000000000000010 : 2
Then, do the same again for the next byte: either BITRSHIFT by 16 (2 bytes) or divide by 65536 (i.e. POWER(256,2))
100110100000001011010000 : 10093264
→ 000000000000000010011010 : 208
& 000000000000000011111111 : 255
= 000000000000000010011010 : 208
If you want to do it all in 1 cell (and have Office 365, for the TEXTJOIN function) then you can use this Array Formula. It used LOG to work out how many bytes there are, and outputs with spaces:
=TEXTJOIN(" ",FALSE,BITAND(BITRSHIFT(A1,8*(ROW($A$1:INDEX($A:$A,CEILING.MATH(LOG($A1,256))))-1)),255))
(As an Array Formula, you will need to use Ctrl+Shift+Enter when you put it in)
function
=ROUNDDOWN(10093264/2^16,0) & " " & ROUNDDOWN(MOD(10093264,2^16)/2^8,0) & " " & ROUNDDOWN(MOD(MOD(10093264,2^16),2^8),0)

Verilog: Aligning valid and invalid bytes from a dynamic input

I'm trying to design a system that takes an 8 byte data input and an 8 bit valid input every clock cycle where each bit on the valid input either validates or invalidates a data byte.
input wire [63:0] d_in;
input wire [7:0] v_in;
The program should process d_in aligning all the valid bytes as follows.
(where B is a valid byte and X is an invalid byte)
Instance 1:
d_in = B1 B2 X X B3 X B4 B5
d_out = B1 B2 B3 B4 B5 X X X
Instance 2:
d_in = X B1 B2 B3 X B4 B5 B6
d_out = B1 B2 B3 B4 B5 B6 X X
I've mainly worked with algorithms before where all bit manipulation was the same every iteration e.g.assign d_out [7:0] = d_in [15:8]; but the fact that the quantity and order of valid bytes can change with every data input means this strategy cannot be used.
My question:
Is there a way to realise this function in using Verilog or VHDL? If so can someone point me towards a high level solution or some relevant reading so I can understand this concept better. I think if I understood at a high level then I'd be able to take a stab a coding it but currently I'm not even sure what I need to be coding.
Thanks
Zach
Since you asked for high level I will give a pseudocode example of something that might work, or at least get you going.
d_out = '0; //Assuming that the X bytes can be set to zero in the output.
bytes = 0;
for i in range(8)
if v_in[i]
d_out[bytes*8 +: 8] = d_in[i*8 +: 8] //Note the +: notation which is not pseudo, but verilog.
bytes++
Now perform this sequential code in an always block and you should be set.
Note: How the synthesized result from this will look is not entierly clear to me, but i suspect it will generate quite a bit of hardware.
I have something similar but not quite.
Input data into a FIFO, pre-calculate a byte-enable with the FIFO entries.
On the output side, read the the byte enable portions and use it to shift out bytes. So there are only eight conditions to satisfy for the byte enable...
1 byte, byteEn(0 downto 1) = "10", shift left 1 byte
2 bytes, byteEn(0 downto 2) = "110", shift left 2 bytes
3 bytes, byteEn(0 downto 3) = "1110", shift left 3 bytes
...and so on...
As you shift, read in the next word using the FIFOs read enable.
Note you will need to take care of when the FIFO is empty but not halt the pipeline so data already present continues to be shifted out.
Not sure how complicated it will be as I have glossed over it a bit.

Decimal to binary conversion for large numbers in 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))

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.

Resources