You are right: it was not working correctly- because the sample numbers were to big. I have wrote in some comments about this to the code
As for unusual grouping of numbers [like in a bank account number]: this is what happens if you spend way too many hours on dealing with various snippets- you see the trees but not the forest
Below is a new correct version of the AutoHotkey test code
Code: Select all
/*
AutoHotkey V1-compatible script for subtracting two large numbers [within 16-digit precision limit] and write conversions with formatted output and right-alignment
*/
; The below are two large test numbers within the safe 64-bit precision limit
NUMBER_A := "4000005000001003"
NUMBER_B := "1000000000001002"
; The below performs subtraction
Result_in_bytes := NUMBER_A - NUMBER_B ; Larger processed numbers will result with incorrect results due to rounding / overflow, because AutoHotkey's internal math uses 64-bit floating point [double], which only supports exact integers up to 15-16 digits [i.e. about 9 quadrillion]
; The below calculates values for each unit
KB := Result_in_bytes / 1024
MB := KB / 1024
GB := MB / 1024
TB := GB / 1024
PB := TB / 1024
EB := PB / 1024
; The below toggles grouping of calculated numbers
Use_formatting_to_groups_for_result_numbers := true ; Change >>true<< to >>false<< to deactivate the feature of numbers being outputted to TXT file being formatted [with groups separated with spaces]
; The below formats calculated results to include 2 decimal places
Formatted_to_bytes := Formatted_further_to_include_spaces(Result_in_bytes, false) . " bytes"
Formatted_to_KB := Formatted_further_to_include_spaces(KB) . " KB"
Formatted_to_MB := Formatted_further_to_include_spaces(MB) . " MB"
Formatted_to_GB := Formatted_further_to_include_spaces(GB) . " GB"
Formatted_to_TB := Formatted_further_to_include_spaces(TB) . " TB"
Formatted_to_PB := Formatted_further_to_include_spaces(PB) . " PB"
Formatted_to_EB := Formatted_further_to_include_spaces(EB) . " EB"
; The below calculates maximum length for the purpose of alignment to the right side
Maximum_length_of_a_digit_based_on_the_bytes_number := StrLen(Formatted_to_bytes)
; The below is a helper function for addition of spaces for alignment
Align_to_right(Text_to_align) {
global Maximum_length_of_a_digit_based_on_the_bytes_number
Length_of_the_line_being_aligned := StrLen(Text_to_align)
if (Length_of_the_line_being_aligned >= Maximum_length_of_a_digit_based_on_the_bytes_number)
return Text_to_align
Required_space_signs_for_padding := Maximum_length_of_a_digit_based_on_the_bytes_number - Length_of_the_line_being_aligned
Padding_spaces := ""
Loop, %Required_space_signs_for_padding%
Padding_spaces .= " " ; Here is the actual white space sign being re-used
return Padding_spaces . Text_to_align
}
; The below deletes the TXT file that is to be created later on, if it already exists
Temporary_TXT_file := A_ScriptDir . "\TEST.txt" ; This defines file location [as the folder from which this AHK file is launched] and its name
if FileExist(Temporary_TXT_file)
{
FileDelete, %Temporary_TXT_file%
Sleep, 1111
}
; The below writes results to TXT file
FileAppend, %Formatted_to_bytes%`n, %Temporary_TXT_file% ; This creates the file
FileAppend, % Align_to_right(Formatted_to_KB) "`n", %Temporary_TXT_file%
FileAppend, % Align_to_right(Formatted_to_MB) "`n", %Temporary_TXT_file%
FileAppend, % Align_to_right(Formatted_to_GB) "`n", %Temporary_TXT_file%
FileAppend, % Align_to_right(Formatted_to_TB) "`n", %Temporary_TXT_file%
FileAppend, % Align_to_right(Formatted_to_PB) "`n", %Temporary_TXT_file%
FileAppend, % Align_to_right(Formatted_to_EB), %Temporary_TXT_file% ; Lack of >>"`n"<< here avoids creation of an extra empty line under the EB line
ExitApp
; The below is a helper function for inserting of a single space sign every 3 digits [from right to left] in the integer part and [with exception of the bytes line] for rounding up fractional parts to 2 decimal places
Formatted_further_to_include_spaces(Number_worked_on, Show_decimal_numbers := true) {
global Use_formatting_to_groups_for_result_numbers
if (Show_decimal_numbers)
Number_worked_on := Round(Number_worked_on, 2) ; This sets the number of decimal places. Choosing >>0<< will simply turn off showing of them [i.e. TXT will show integers]
else
Number_worked_on := Round(Number_worked_on)
StringSplit, Parts_split, Number_worked_on, .
Integer_part := Parts_split1
if (!Use_formatting_to_groups_for_result_numbers) {
if (Parts_split0 > 1)
return Integer_part . "." . Parts_split2
else
return Integer_part
}
Number_with_added_spaces := ""
StringLen, Length_of_integer_part, Integer_part
Current_position_in_integer_part := Length_of_integer_part
while (Current_position_in_integer_part > 3) {
Number_with_added_spaces := " " . SubStr(Integer_part, Current_position_in_integer_part - 2, 3) . Number_with_added_spaces
Current_position_in_integer_part -= 3
}
Number_with_added_spaces := SubStr(Integer_part, 1, Current_position_in_integer_part) . Number_with_added_spaces
if (Parts_split0 > 1)
return Number_with_added_spaces . "." . Parts_split2
else
return Number_with_added_spaces
}
/*
To manually check calculations outputted to the TXT file use services like:
https://thistothatcalculator.com/bytes-to-tb-calculator/
https://unitconverters.net/data-storage-converter.html
https://whatsabyte.com/P1/byteconverter.htm
*/
and its batch version
Code: Select all
@echo off
> "TEST.ahk" (
echo /*
echo.
echo AutoHotkey V1-compatible script for subtracting two large numbers [within 16-digit precision limit] and write conversions with formatted output and right-alignment
echo.
echo */
echo.
echo ; The below are two large test numbers within the safe 64-bit precision limit
echo NUMBER_A := "4000005000001003"
echo NUMBER_B := "1000000000001002"
echo.
echo ; The below performs subtraction
echo Result_in_bytes := NUMBER_A - NUMBER_B ; Larger processed numbers will result with incorrect results due to rounding / overflow, because AutoHotkey's internal math uses 64-bit floating point [double], which only supports exact integers up to 15-16 digits [i.e. about 9 quadrillion]
echo.
echo ; The below calculates values for each unit
echo KB := Result_in_bytes / 1024
echo MB := KB / 1024
echo GB := MB / 1024
echo TB := GB / 1024
echo PB := TB / 1024
echo EB := PB / 1024
echo.
echo ; The below toggles grouping of calculated numbers
echo Use_formatting_to_groups_for_result_numbers := true ; Change ^>^>true^<^< to ^>^>false^<^< to deactivate the feature of numbers being outputted to TXT file being formatted [with groups separated with spaces]
echo.
echo ; The below formats calculated results to include 2 decimal places
echo Formatted_to_bytes := Formatted_further_to_include_spaces^(Result_in_bytes, false^) . " bytes"
echo Formatted_to_KB := Formatted_further_to_include_spaces^(KB^) . " KB"
echo Formatted_to_MB := Formatted_further_to_include_spaces^(MB^) . " MB"
echo Formatted_to_GB := Formatted_further_to_include_spaces^(GB^) . " GB"
echo Formatted_to_TB := Formatted_further_to_include_spaces^(TB^) . " TB"
echo Formatted_to_PB := Formatted_further_to_include_spaces^(PB^) . " PB"
echo Formatted_to_EB := Formatted_further_to_include_spaces^(EB^) . " EB"
echo.
echo ; The below calculates maximum length for the purpose of alignment to the right side
echo Maximum_length_of_a_digit_based_on_the_bytes_number := StrLen^(Formatted_to_bytes^)
echo.
echo ; The below is a helper function for addition of spaces for alignment
echo Align_to_right^(Text_to_align^) {
echo global Maximum_length_of_a_digit_based_on_the_bytes_number
echo Length_of_the_line_being_aligned := StrLen^(Text_to_align^)
echo if ^(Length_of_the_line_being_aligned ^>= Maximum_length_of_a_digit_based_on_the_bytes_number^)
echo return Text_to_align
echo Required_space_signs_for_padding := Maximum_length_of_a_digit_based_on_the_bytes_number - Length_of_the_line_being_aligned
echo Padding_spaces := ""
echo Loop, %%Required_space_signs_for_padding%%
echo Padding_spaces .= " " ; Here is the actual white space sign being re-used
echo return Padding_spaces . Text_to_align
echo }
echo.
echo ; The below deletes the TXT file that is to be created later on, if it already exists
echo Temporary_TXT_file := A_ScriptDir . "\TEST.txt" ; This defines file location [as the folder from which this AHK file is launched] and its name
echo if FileExist^(Temporary_TXT_file^)
echo {
echo FileDelete, %%Temporary_TXT_file%%
echo Sleep, 1111
echo }
echo.
echo ; The below writes results to TXT file
echo FileAppend, %%Formatted_to_bytes%%`n, %%Temporary_TXT_file%% ; This creates the file
echo FileAppend, %% Align_to_right^(Formatted_to_KB^) "`n", %%Temporary_TXT_file%%
echo FileAppend, %% Align_to_right^(Formatted_to_MB^) "`n", %%Temporary_TXT_file%%
echo FileAppend, %% Align_to_right^(Formatted_to_GB^) "`n", %%Temporary_TXT_file%%
echo FileAppend, %% Align_to_right^(Formatted_to_TB^) "`n", %%Temporary_TXT_file%%
echo FileAppend, %% Align_to_right^(Formatted_to_PB^) "`n", %%Temporary_TXT_file%%
echo FileAppend, %% Align_to_right^(Formatted_to_EB^), %%Temporary_TXT_file%% ; Lack of ^>^>"`n"^<^< here avoids creation of an extra empty line under the EB line
echo.
echo ExitApp
echo.
echo ; The below is a helper function for inserting of a single space sign every 3 digits [from right to left] in the integer part and [with exception of the bytes line] for rounding up fractional parts to 2 decimal places
echo Formatted_further_to_include_spaces^(Number_worked_on, Show_decimal_numbers := true^) {
echo global Use_formatting_to_groups_for_result_numbers
echo.
echo if ^(Show_decimal_numbers^)
echo Number_worked_on := Round^(Number_worked_on, 2^) ; This sets the number of decimal places. Choosing ^>^>0^<^< will simply turn off showing of them [i.e. TXT will show integers]
echo else
echo Number_worked_on := Round^(Number_worked_on^)
echo.
echo StringSplit, Parts_split, Number_worked_on, .
echo Integer_part := Parts_split1
echo.
echo if ^(!Use_formatting_to_groups_for_result_numbers^) {
echo if ^(Parts_split0 ^> 1^)
echo return Integer_part . "." . Parts_split2
echo else
echo return Integer_part
echo }
echo.
echo Number_with_added_spaces := ""
echo StringLen, Length_of_integer_part, Integer_part
echo Current_position_in_integer_part := Length_of_integer_part
echo.
echo while ^(Current_position_in_integer_part ^> 3^) {
echo Number_with_added_spaces := " " . SubStr^(Integer_part, Current_position_in_integer_part - 2, 3^) . Number_with_added_spaces
echo Current_position_in_integer_part -= 3
echo }
echo Number_with_added_spaces := SubStr^(Integer_part, 1, Current_position_in_integer_part^) . Number_with_added_spaces
echo.
echo if ^(Parts_split0 ^> 1^)
echo return Number_with_added_spaces . "." . Parts_split2
echo else
echo return Number_with_added_spaces
echo }
echo.
echo /*
echo.
echo To manually check calculations outputted to the TXT file use services like:
echo.
echo https://thistothatcalculator.com/bytes-to-tb-calculator/
echo https://unitconverters.net/data-storage-converter.html
echo https://whatsabyte.com/P1/byteconverter.htm
echo.
echo */
)
pause
which produces the very same AHK file - with exception of adding to it one extra empty line at its very end [that I have no idea where its coming from and have failed at removing it]
The AHK when run produces such text
Code: Select all
3 000 005 000 000 001 bytes
2 929 692 382 812.50 KB
2 861 027 717.59 MB
2 793 972.38 GB
2 728.49 TB
2.66 PB
0.00 EB