Home > other >  How to truncate a number to a fixed size without rounding when displaying it with Console.WriteLine(
How to truncate a number to a fixed size without rounding when displaying it with Console.WriteLine(

Time:10-13

I'm trying to format a number in a very specific way when displaying it, I've tried messing around with String.Format but couldn't find a way to make this work exactly as I needed.

For example, let's way that I have a variable of type Double with the value "123459.7889" and that I want to format it as "459.788" (000.000) but only during Console.WriteLine() and without rounding or changing the internal value of the number. The full value of the number would not show up and it should technically "overflow" the string because it should only print the first 3 numbers to the left of the decimal point.

Here are some example inputs and example outputs:

12345.678 formatted to "000.000" would become 345.678

1000000.678 formatted to "000.000" would become 000.678

1.777888 formatted to "000.000" would become 001.777

99999.9 formatted to "000.000" would become 999.900

Basically, no matter the internal size of the number, the formatted output should always be the 3 numbers to the left of the decimal point and the 3 numbers to the right of the decimal point with zeros to replace the missing spaces if there's any.

I've tried looking at the examples on the C# documentation and found this:

double value = 123459.7889;
string result = String.Format("{0,8:00000000} {0,8:00000000.000}", value);
Console.WriteLine(result);

But it doesn't work exactly like I needed it to. When running it the numbers are rounded so it becomes 00123459.789 instead of 00123459.788 for example and if the number grows it no longer stays at that fixed size.

CodePudding user response:

try this:

double value = 123459.7889;
Console.WriteLine((Math.Truncate(Math.Abs(value) % 1000)   double.Parse((Math.Round(Math.Abs(value), 3, MidpointRounding.ToZero) -
               Math.Truncate(Math.Abs(value))).ToString(".000"))).ToString("000.000"));

value= 123459.7889; result=345.678

value= 1000000.678; result=000.678

value= 1.777888; result=001.777

value= 99999.9; result=999.900

value= 152; result=152 .000

value= -100.02; result=100.020

value= 10.0005; result=010.000

CodePudding user response:

You shouldn't need to convert to string, nor should you rely on splitting on a character that may or may not be the decimal character in the language you are running. You can do all the calculations on the numbers and then format the output without allocating any strings except for the result.

public static string FormatNumber(double number)
{
    int first = ((int)number)00;
    int second = (int)Math.Truncate((number-(int)number)*1000)00;
    return $"{first:000}.{second:000}";
}

CodePudding user response:

We can use PadLeft and PadRight to fill up zeros when value characters are not enough.

Implementation:

static void Main(string[] args)
{
    double value = 1.12;
    string valueStr = value.ToString().Replace("-", ""); // convert to string

    // check if value does not contain decimal and add
    if (!valueStr.ToString().Contains("."))
        valueStr  = valueStr   ".0"; // add decimal part

    var arr = valueStr.ToString().Split(".");

    string intValue = arr[0]; //1
    intValue = intValue.PadLeft(3,'0'); //001
    intValue = intValue.Substring(intValue.Length - 3, 3); //001

    string decimalValue = arr[1]; //12
    decimalValue = decimalValue.PadRight(3,'0'); //120
    decimalValue = decimalValue.Substring(0, 3); //120

    string result = $"{intValue}.{decimalValue}";
    Console.WriteLine(result);
}

Result:

12345.678   > 345.678
1000000.678 > 000.678
1.777888    > 001.777
99999.9     > 999.900
152         > 152.000
-100.02     > 100.020
-10.0005    > 010.000

CodePudding user response:

static string Format(double number)
{
    return string.Format("{0:N3}", number % 1000).PadLeft(7,'0');
}

How it works:

  1. Remove the upper digits using modulus (%)
  2. Format to three decimal places using a format string
  3. Pad left using PadLeft()

Full example:

using System;
using System.Collections.Generic;
public class Program
{
    public static void Main()
    {
        var tests = new Dictionary<double,string>
        {
            { 12345.678D, "345.678" },
            { 1000000.678, "000.678" },
            { 1.777888, "001.778" },
            { 99999.9, "999.900"}
        };

        foreach (var pair in tests)
        {
            Console.WriteLine("Expected: {0}  Actual: {1}", pair.Value, Format(pair.Key));
        }

    }

    static string Format(double number)
    {
        return string.Format("{0:N3}", number % 1000).PadLeft(7,'0');
    }
}

Output:

Expected: 345.678  Actual: 345.678
Expected: 000.678  Actual: 000.678
Expected: 001.778  Actual: 001.778
Expected: 999.900  Actual: 999.900

Fiddle

CodePudding user response:

try this

int i = value.ToString().IndexOf(".");
string result = string.Concat(value.ToString().Substring(i - 3, 3),".", value.ToString().Substring(i   1, 3));
Console.WriteLine(result);
  •  Tags:  
  • c#
  • Related