Suffixation of decimal numbers: Difference between revisions

Added FreeBASIC
m (→‎{{header|Phix}}: added syntax colouring the hard way)
(Added FreeBASIC)
 
(3 intermediate revisions by 3 users not shown)
Line 122:
{{trans|Python}}
 
<langsyntaxhighlight lang="11l">F suffize(numstr, digits = -1, base = 10)
V suffixes = [‘’, ‘K’, ‘M’, ‘G’, ‘T’, ‘P’, ‘E’, ‘Z’, ‘Y’, ‘X’, ‘W’, ‘V’, ‘U’, ‘googol’]
 
Line 165:
p(‘456,789,100,000.000e+00’, 0, 10)
p(‘+16777216’, -1, 2)
p(‘1.2e101’)</langsyntaxhighlight>
 
{{out}}
Line 179:
1.2e101 : 12googol
</pre>
 
 
=={{header|C#}}==
{{trans|Python}}
<syntaxhighlight lang="C#">
using System;
using System.Globalization;
 
public class NumberSuffixer
{
private static readonly string[] Suffixes = { "", "K", "M", "G", "T", "P", "E", "Z", "Y", "X", "W", "V", "U", "googol" };
 
public static string Suffize(string num, int? digits = null, int baseNum = 10)
{
int exponentDistance = baseNum == 2 ? 10 : 3;
num = num.Trim().Replace(",", "");
string numSign = num[0] == '+' || num[0] == '-' ? num.Substring(0, 1) : "";
 
num = numSign != "" ? num.Substring(1) : num;
double number = Math.Abs(double.Parse(num, CultureInfo.InvariantCulture));
 
int suffixIndex;
if (baseNum == 10 && number >= 1e100)
{
suffixIndex = 13;
number /= 1e100;
}
else if (number > 1)
{
double magnitude = Math.Floor(Math.Log(number, baseNum));
suffixIndex = Math.Min((int)Math.Floor(magnitude / exponentDistance), 12);
number /= Math.Pow(baseNum, exponentDistance * suffixIndex);
}
else
{
suffixIndex = 0;
}
 
string numStr;
if (digits.HasValue)
{
numStr = number.ToString($"F{digits}", CultureInfo.InvariantCulture);
}
else
{
numStr = number.ToString("F3", CultureInfo.InvariantCulture).TrimEnd('0').TrimEnd('.');
}
 
return numSign + numStr + Suffixes[suffixIndex] + (baseNum == 2 ? "i" : "");
}
 
public static void Main(string[] args)
{
var tests = new (string, int?, int?)[]
{
("87,654,321", null, null),
("-998,877,665,544,332,211,000", 3, null),
("+112,233", 0, null),
("16,777,216", 1, null),
("456,789,100,000,000", 2, null),
("456,789,100,000,000", 2, 10),
("456,789,100,000,000", 5, 2),
("456,789,100,000.000e+00", 0, 10),
("+16777216", null, 2),
("1.2e101", null, null),
};
 
foreach (var test in tests)
{
Console.WriteLine($"{test.Item1}, {test.Item2?.ToString() ?? "null"}, {test.Item3?.ToString() ?? "null"} : " +
$"{Suffize(test.Item1, test.Item2, test.Item3 ?? 10)}");
}
}
}
</syntaxhighlight>
{{out}}
<pre>
87,654,321, null, null : 87.654M
-998,877,665,544,332,211,000, 3, null : -998.878E
+112,233, 0, null : +112K
16,777,216, 1, null : 16.8M
456,789,100,000,000, 2, null : 456.79T
456,789,100,000,000, 2, 10 : 456.79T
456,789,100,000,000, 5, 2 : 415.44727Ti
456,789,100,000.000e+00, 0, 10 : 457G
+16777216, null, 2 : +16Mi
1.2e101, null, null : 12googol
 
</pre>
 
=={{header|FreeBASIC}}==
{{trans|Nim}}
<syntaxhighlight lang="vbnet">#include "string.bi"
 
#define MIN(a, b) iif((a) < (b), (a), (b))
 
Dim Shared As String*6 Suffixes(13) = {"", "K", "M", "G", "T", "P", "E", "Z", "Y", "X", "W", "V", "U", "googol"}
 
Function ReplaceString(Byval s As String, Byval find As String, Byval replaceWith As String) As String
Dim posic As Integer
posic = Instr(s, find)
While posic > 0
s = Left(s, posic - 1) & replaceWith & Mid(s, posic + Len(find))
posic = Instr(posic + Len(replaceWith), s, find)
Wend
Return s
End Function
 
Function suffize(num As String, digits As Integer, bbase As Integer) As String
Dim As Integer exponentDist
exponentDist = Iif(bbase = 2, 10, 3)
Dim As String numSign = ""
If Left(num, 1) = "+" Or Left(num, 1) = "-" Then
numSign = Left(num, 1)
num = Mid(num, 2)
End If
num = ReplaceString(num, ",", "")
Dim As Double n = Val(num)
Dim As Integer suffixIndex
If bbase = 10 And n >= 1e100 Then
suffixIndex = 13
n /= 1e100
Elseif n > 1 Then
Dim As Integer magnitude = Int(Log(n) / Log(bbase))
suffixIndex = MIN(magnitude \ exponentDist, 12)
n /= bbase ^ (exponentDist * suffixIndex)
Else
suffixIndex = 0
End If
Dim As String numStr
If digits > 0 Then
numStr = Format(n, "0." & String(digits, "#"))
Elseif digits = 0 Then
numStr = Format(Int(n), "0")
Else
numStr = Format(n, "0.###")
End If
Return numSign & numStr & Suffixes(suffixIndex) & Iif(bbase = 2, "i", "")
End Function
 
Print "[87,654,321]: "; suffize("87,654,321", 3, 10)
Print "[-998,877,665,544,332,211,000 / digits = 3]: "; suffize("-998877665544332211000", 3, 10)
Print "[+112,233 / digits = 0]: "; suffize("+112233", 0, 10)
Print "[16,777,216 / digits = 1]: "; suffize("16777216", 1, 10)
Print "[456,789,100,000,000 / digits = 2]: "; suffize("456789100000000", 2, 10)
Print "[456,789,100,000,000 / digits = 2 / base = 10]: "; suffize("456789100000000", 2, 10)
Print "[456,789,100,000,000 / digits = 5 / base = 2]: "; suffize("456789100000000", 5, 2)
Print "[456,789,100,000.000e+000 / digits = 0 / base = 10]: "; suffize("456789100000", 0, 10)
Print "[+16777216 / base = 2]: "; suffize("+16777216", 3, 2)
Print "[1.2e101]: "; suffize("1.2e101", 3, 10)
 
Sleep</syntaxhighlight>
 
=={{header|Go}}==
As go doesn't support either function overloading or optional arguments, we just pass a single string to the suffize function and then split out what we need.
<langsyntaxhighlight lang="go">package main
 
import (
Line 300 ⟶ 457:
suffize(test)
}
}</langsyntaxhighlight>
 
{{out}}
Line 371 ⟶ 528:
 
=={{header|Julia}}==
<langsyntaxhighlight lang="julia">using Printf
 
const suf = Dict{BigInt, String}(BigInt(1) => "", BigInt(10)^100 => "googol",
Line 432 ⟶ 589:
(n > 2) ? lpad(l[3], 3) : " ", " : ", s)
end
</langsyntaxhighlight>{{out}}
<pre>
87,654,321 : 87.654321M
Line 448 ⟶ 605:
=={{header|Nim}}==
{{trans|Python}}
<langsyntaxhighlight Nimlang="nim">import math, strutils
 
const
Line 504 ⟶ 661:
suffize("+16777216", base = 2)
echo "[1.2e101]: ",
suffize("1.2e101")</langsyntaxhighlight>
 
{{out}}
Line 520 ⟶ 677:
=={{header|Perl}}==
{{trans|Raku}}
<langsyntaxhighlight lang="perl">use List::Util qw(min max first);
 
sub sufficate {
Line 597 ⟶ 754:
);
 
printf "%33s : %s\n", $_, sufficate(split ' ', $_) for @tests;</langsyntaxhighlight>
{{out}}
<pre> 87,654,321 : 87.654321M
Line 618 ⟶ 775:
at least with any fraction that is not an exact sum of half, quarter, etc, so for
that reason this uses bigatom, since that can hold numbers with absolute accuracy.
<!--<langsyntaxhighlight Phixlang="phix">(phixonline)-->
<span style="color: #008080;">include</span> <span style="color: #000000;">builtins</span><span style="color: #0000FF;">/</span><span style="color: #000000;">bigatom</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span>
Line 680 ⟶ 837:
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%30s : %s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">ti</span><span style="color: #0000FF;">,</span><span style="color: #000000;">res</span><span style="color: #0000FF;">})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<!--</langsyntaxhighlight>-->
{{out}}
<pre>
Line 701 ⟶ 858:
Tested in Python 3.7.3<br />
Chose 3 places after decimal (where applicable) as default rounding precision. Number to suffize taken as a string. There are some edge cases where this fails due to binary arithmetic differing from decimal arithmetic and things not rounding nicely.
<langsyntaxhighlight lang="python">
import math
import os
Line 746 ⟶ 903:
for test in tests:
print(' '.join(str(i) for i in test) + ' : ' + suffize(*test))
</syntaxhighlight>
</lang>
 
{{out}}
Line 773 ⟶ 930:
If you desire the number to be rounded, pass in a number representing the placed past the decimal to round to. If you pass in a negative number for rounding, it will round to a negative number of places past the decimal.
 
<syntaxhighlight lang="raku" perl6line>sub sufficate ($val is copy, $type is copy = 'M', $round is copy = Any) {
if +$type ~~ Int { $round = $type; $type = 'M' }
my $s = '';
Line 825 ⟶ 982:
;
 
printf "%33s : %s\n", $_, sufficate(|.words) for @tests;</langsyntaxhighlight>
{{out}}
<pre> 87,654,321 : 87.654321M
Line 842 ⟶ 999:
 
=={{header|REXX}}==
<langsyntaxhighlight lang="rexx">/*REXX program to add a (either metric or "binary" metric) suffix to a decimal number.*/
@.= /*default value for the stemmed array. */
parse arg @.1 /*obtain optional arguments from the CL*/
Line 904 ⟶ 1,061:
 
if n=0 then j=0 /*N = 0? Don't use any suffix. */
return sig||strip(n||substr(@, j+1,1))!.b /*add sign, suffixes, strip blanks.*/</langsyntaxhighlight>
{{out|output|text=&nbsp; when using the internal default inputs:}}
 
Line 969 ⟶ 1,126:
=={{header|VBA}}==
VBA has support for 64 bit integers on 64 bit platforms. The program below was developed on a 32 bit platform.
<langsyntaxhighlight lang="vb">Private Function suffize(number As String, Optional sfractiondigits As String, Optional base As String) As String
Dim suffix As String, parts() As String, exponent As String
Dim fractiondigits As Integer, nsuffix As Integer, flag As Boolean
Line 1,104 ⟶ 1,261:
Debug.Print " new number = "; suffize(tt(0), f, r)
Next i
End Sub</langsyntaxhighlight>
{{out|output|text=&nbsp; when using the internal default inputs:}}
<pre>------------------------------------------------
Line 1,161 ⟶ 1,318:
{{libheader|Wren-big}}
{{libheader|Wren-fmt}}
<langsyntaxhighlight ecmascriptlang="wren">import "./big" for BigRat
import "./fmt" for Fmt
 
var suffixes = " KMGTPEZYXWVU"
Line 1,240 ⟶ 1,397:
"1e39", // there isn't a big enough suffix for this one but it's less than googol
]
for (test in tests) suffize.call(test)</langsyntaxhighlight>
 
{{out}}
Line 1,313 ⟶ 1,470:
{{libheader|GMP}} GNU Multiple Precision Arithmetic Library (big ints)
Error checking is nonexistent.
<langsyntaxhighlight lang="zkl">var [const] BI=Import.lib("zklBigNum"); // GMP
var metric, binary, googol=BI("1e100");
metric,binary = metricBin();
Line 1,357 ⟶ 1,514:
.zipWith(b.append,[10..10*(ss.len()),10].apply(BI(2).pow)); // Binary
return(m.filter22("".isType), b.filter22("".isType)); # split to ((strings),(nums))
}</langsyntaxhighlight>
<langsyntaxhighlight lang="zkl">testCases:=T(
"87,654,321",
"-998,877,665,544,332,211,000 3",
Line 1,380 ⟶ 1,537:
test=test.split();
"%33s : %s".fmt(test.concat(" "),sufficate(test.xplode())).println();
}</langsyntaxhighlight>
{{out}}
<pre>
2,136

edits