Showing posts with label C# General. Show all posts
Showing posts with label C# General. Show all posts

SQL Banker's Rounding Function

The Banker's Rounding, also known as the Gaussian Rounding or Rounding to Even, rounds a given number if its fraction is half to the nearest even number.

The bellow SQL function rounds any given decimal number to a number of given digits and returns the rounded decimal number. It reads the number from right to left depending on the number of digits required and then rounds it. If the fraction is not half, then common rounding takes place.

CREATE FUNCTION [dbo].[BankersRounding]
(
	@value DECIMAL(28, 10),
	@digits INT
)

RETURNS DECIMAL (28, 10)
AS
BEGIN

	DECLARE @roundedValue DECIMAL(28, 10)
	DECLARE @roundingType INT 
	
		IF (ABS(@value - ROUND(@value, @digits, 1)) * POWER(10, @digits + 1) = 5)
			BEGIN
			
				IF (ROUND(ABS(@value) * POWER(10, @digits), 0, 1) % 2 = 0)
					BEGIN
						SET @roundingType = 1 
					END
				ELSE
					BEGIN
						SET @roundingType = 0
					END
						
				SET @roundedValue = ROUND(@value, @digits, @roundingType)
			END
				
		ELSE
			BEGIN
				SET @roundedValue = ROUND(@value, @digits)
			END
						
	RETURN @roundedValue
END

In C# there's the Round method inside the Math class that can take an enumeration overload called MidpointRounding.ToEven that does the exact same thing.

Here's an example:

using System;

namespace BankersRoundingProject
{
    public class BankersRounding
    {
        public static decimal GetRoundedValue(decimal value, int digits)
        {
            return Math.Round(value, digits, MidpointRounding.ToEven);
        }
    }
}

Temperature converting

In this post I'll try to explain you how to convert temperatures from Celsius to Fahrenheit or vice versa. I will create a small WinForms application that actually does that.

I used two doubles to store the temperature's values (one for Celsius and one for Fahrenheit), two labels (of which one will be displayed after the actual transformation takes places and will contain the transformed value), one combobox and one textbox. Oh... and almost forgot about the button that triggers the transformation and displays the result.

One more thing you will notice is that I've used Math.Round with two decimals to get a nice transformation result and I've used the String.Format method to display the transformed value instead of the usual concatenation.

using System;
using System.Drawing;
using System.Windows.Forms;

namespace TemperatureTrasformer
{
    public partial class mainForm : Form
    {
        double celsius;
        double fahrenheit;

        ComboBox cboxTempType;
        TextBox txtTemp;
        Label lblInitial;
        Label lblResult;
        Button btnConvert;

        public mainForm()
        {
            InitializeComponent();

            //Set up the form's proprieties
            this.Text = "Temperature Converter";
            this.ClientSize = new Size(250, 150);
            this.MaximizeBox = false;
            this.StartPosition = FormStartPosition.CenterScreen;
            this.FormBorderStyle = FormBorderStyle.FixedSingle;

            //Set up the form's controls
            lblInitial = new Label();
            lblInitial.Location = new Point(10, 10);
            lblInitial.AutoSize = true;
            lblInitial.Text = "Enter the temperature you want to convert:";

            txtTemp = new TextBox();
            txtTemp.Location = new Point(10, lblInitial.Bottom + 5); 
            txtTemp.Width = 100;

            cboxTempType = new ComboBox();
            cboxTempType.Location = new Point(txtTemp.Right + 10, lblInitial.Bottom + 5);
            cboxTempType.Width = 100;
            cboxTempType.DropDownStyle = ComboBoxStyle.DropDownList;
            cboxTempType.Items.Add("Celsius");
            cboxTempType.Items.Add("Fahrenheit");
            cboxTempType.SelectedIndex = 0;

            btnConvert = new Button();
            btnConvert.Text = "Convert";
            btnConvert.Location = new Point(10, txtTemp.Bottom + 10);
            btnConvert.AutoSize = true;
            btnConvert.Click += new EventHandler(btnConvert_Click);

            lblResult = new Label();
            lblResult.Location = new Point(10, btnConvert.Bottom + 10);
            lblResult.AutoSize = true;

            this.Controls.Add(lblInitial);
            this.Controls.Add(cboxTempType);
            this.Controls.Add(txtTemp);
            this.Controls.Add(btnConvert);
        }

        void btnConvert_Click(object sender, EventArgs e)
        {
            //Convert to Fahrenheit
            if (cboxTempType.SelectedIndex == 0)
            {
                celsius = Convert.ToDouble(txtTemp.Text);
                fahrenheit = Math.Round((celsius * 9) / 5 + 32, 2);
                lblResult.Text = String.Format("The temperature in Fahrenheit is {0} degrees", fahrenheit);
                this.Controls.Add(lblResult);
            }
            //Convert to Celsius
            else if (cboxTempType.SelectedIndex == 1)
            {
                fahrenheit = Convert.ToDouble(txtTemp.Text);
                celsius = Math.Round((fahrenheit - 32) / 9 * 5, 2);
                lblResult.Text = String.Format("The temperature in Celsius is {0} degrees", celsius);
                this.Controls.Add(lblResult);
            }
        }
    }
}

Sorting Combobox Items Alphabetically

To sort a collection of items inside a combobox alphabetically, one way to do it would be to use the SortDescription class. For this, first you need to add the System.ComponentModel namespace. Then initialize a new SortDescription class in which you can tell by what and how to arrange the list. And finally simply add the class to the combobox you wish to be arranged. In case you want to arrange a simple combobox (only one thing to arrange it by) use the "Content" string when initializing the class as shown in the example bellow:

SortDescription sd = new SortDescription("Content", ListSortDirection.Ascending);
comboBox1.Items.SortDescriptions.Add(sd);

Get The Total Size of Multiple HDD

The following code will show you how it can be retrieved the total size of multiple HDDs installed on your system. Using the same method you can do this for available free space. I've also converted bytes to GB as the value is retrieved in bytes. For this you can use the Size property from the Win32_DiskDrive class:

private static String getHDDsize()
        {
            Double sum = 0;

            ManagementObjectSearcher mos = new ManagementObjectSearcher("Select * From Win32_DiskDrive");

            foreach (ManagementObject item in mos.Get())
            {
                double HDD_size = Convert.ToDouble(item["Size"]);
                sum += HDD_size;
            }

            return Convert.ToString(Math.Round(sum / 1073741824, 2)) + " GB";
        }

Retrieving the System's Total Physical Memory

Recently I was creating an app in which I needed to display the total physical memory inside a label. At first I was tempted to retrieve the memory using the Capacity property from Win32_PhysicalMemory, but it seems that this property retrieves the memory from each module. Although it does the job, I found out that is more efficient to retrieve the total physical memory using the TotalPhysicalMemory property from the Win32_ComputerSystem WMI class.

The following code shows you how to retrieve it using a foreach loop. Note that this property retrieves the memory in bytes and I've did some calculations to display it in GB. Then, this method can be used to display the memory amount inside a label... or whatever.

private static String getRAMsize()
        {
            ManagementClass mc = new ManagementClass("Win32_ComputerSystem");
            ManagementObjectCollection moc = mc.GetInstances();
            foreach (ManagementObject item in moc)
            {
                return Convert.ToString(Math.Round(Convert.ToDouble(item.Properties["TotalPhysicalMemory"].Value) / 1073741824, 2)) + " GB";
            }

            return "RAMsize";
        }