mvslovers / brexx370

MVS version of Vasilis Vlachoudis awesome rexx implementation
46 stars 11 forks source link

Truncate Rounding #72

Open mainframed opened 4 years ago

mainframed commented 4 years ago

Based on IBM documentation and ooREXX truncate should round based on DIGITS. The default on most rexx systems is 9.

To test truncate and rounding i wrote the following script:

/* REXX */
parse version v
say v
say "Default digits:" digits()
say "test 4" trunc(127.2) "==" 127.00
if trunc(127.2) \== 127.00 then do
   say '  failed in test 4 '
  rc = 8
end
say "test 16" trunc(10000000.05,2) " ==" 10000000.10
if trunc(10000000.05,2) \== 10000000.10 then do
   say '  failed in test 16 '
  rc = 8
end
say "test 19" trunc(10000000.55,2) " ==" 10000000.60
if trunc(10000000.55,2) \== 10000000.60 then do
   say '  failed in test 19 '
  rc = 8
end
say "test 20" trunc(10000000.055,2) " ==" 10000000.10
if trunc(10000000.055,2) \== 10000000.10 then do
   say '  failed in test 20 '
  rc = 8
end
say "test 22" trunc(10000000.04,2) ' ==' 10000000.00
if trunc(10000000.04,2) \== 10000000.00 then do
   say '  failed in test 22 '
  rc = 8
end
say "test 23" trunc(10000000.045,2) " ==" 10000000.00
if trunc(10000000.045,2) \== 10000000.00 then do
   say '  failed in test 23 '
  rc = 8
end
say "test 24" trunc(10000000.45,2) " ==" 10000000.50
if trunc(10000000.45,2) \== 10000000.50 then do
   say '  failed in test 24 '
  rc = 8
end
say "test 25" trunc(10000000.05,2) " ==" 10000000.10
if trunc(10000000.05,2) \== 10000000.10 then do
   say '  failed in test 25 '
  rc = 8
end
say "test 26" trunc(10000000.05,2) " ==" 10000000.10 
if trunc(10000000.05,2) \== 10000000.10 then do
   say '  failed in test 26 '
  rc = 8
end
say "test 27" trunc(10000000.05,2) " ==" 10000000.10
if trunc(10000000.05,2) \== 10000000.10 then do
   say '  failed in test 27 '
  rc = 8
end
say "test 30" trunc(99999999.99,2) "==" 100000000.00
if trunc(99999999.99,2) \== 100000000.00 then do
   say '  failed in test 30 '
  rc = 8
end
say "test 78" trunc(123.12345,5) "==" 123.12345
if trunc(123.12345,5) \== 123.12345 then do
   say '  failed in test 78 '
  rc = 8
end
say "=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-"
say "Changing digits to 30"
NUMERIC DIGITS 30
say "test 4" trunc(127.2) "==" 127.00
if trunc(127.2) \== 127.00 then do
   say '  failed in test 4 '
  rc = 8
end
say "test 16" trunc(10000000.05,2) " ==" 10000000.10
if trunc(10000000.05,2) \== 10000000.10 then do
   say '  failed in test 16 '
  rc = 8
end
say "test 19" trunc(10000000.55,2) " ==" 10000000.60
if trunc(10000000.55,2) \== 10000000.60 then do
   say '  failed in test 19 '
  rc = 8
end
say "test 20" trunc(10000000.055,2) " ==" 10000000.10
if trunc(10000000.055,2) \== 10000000.10 then do
   say '  failed in test 20 '
  rc = 8
end
say "test 22" trunc(10000000.04,2) ' ==' 10000000.00
if trunc(10000000.04,2) \== 10000000.00 then do
   say '  failed in test 22 '
  rc = 8
end
say "test 23" trunc(10000000.045,2) " ==" 10000000.00
if trunc(10000000.045,2) \== 10000000.00 then do
   say '  failed in test 23 '
  rc = 8
end
say "test 24" trunc(10000000.45,2) " ==" 10000000.50
if trunc(10000000.45,2) \== 10000000.50 then do
   say '  failed in test 24 '
  rc = 8
end
say "test 25" trunc(10000000.05,2) " ==" 10000000.10
if trunc(10000000.05,2) \== 10000000.10 then do
   say '  failed in test 25 '
  rc = 8
end
say "test 26" trunc(10000000.05,2) " ==" 10000000.10 
if trunc(10000000.05,2) \== 10000000.10 then do
   say '  failed in test 26 '
  rc = 8
end
say "test 27" trunc(10000000.05,2) " ==" 10000000.10
if trunc(10000000.05,2) \== 10000000.10 then do
   say '  failed in test 27 '
  rc = 8
end
say "test 30" trunc(99999999.99,2) "==" 100000000.00
if trunc(99999999.99,2) \== 100000000.00 then do
   say '  failed in test 30 '
  rc = 8
end
say "test 78" trunc(123.12345,5) "   ==" 123.12345
if trunc(123.12345,5) \== 123.12345 then do
   say '  failed in test 78 '
  rc = 8
end

Below will be three outputs:

  1. From an online rexx interpreter from: https://www.tutorialspoint.com/execute_rexx_online.php
  2. IBM z/OS 2.4
  3. Brexx 370 on tk4-

Testing

  1. Online interpreter
REXX-ooRexx_4.2.0(MT)_64-bit 6.04 31 Dec 2013
Default digits: 9
test 4 127 == 127.00
  failed in test 4 
test 16 10000000.10  == 10000000.10
test 19 10000000.60  == 10000000.60
test 20 10000000.10  == 10000000.10
test 22 10000000.00  == 10000000.00
test 23 10000000.00  == 10000000.00
test 24 10000000.50  == 10000000.50
test 25 10000000.10  == 10000000.10
test 26 10000000.10  == 10000000.10
test 27 10000000.10  == 10000000.10
test 30 100000000.00 == 100000000.00
test 78 123.12345 == 123.12345
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
Changing digits to 30
test 4 127 == 127.00
  failed in test 4 
test 16 10000000.05  == 10000000.10
  failed in test 16 
test 19 10000000.55  == 10000000.60
  failed in test 19 
test 20 10000000.05  == 10000000.10
  failed in test 20 
test 22 10000000.04  == 10000000.00
  failed in test 22 
test 23 10000000.04  == 10000000.00
  failed in test 23 
test 24 10000000.45  == 10000000.50
  failed in test 24 
test 25 10000000.05  == 10000000.10
  failed in test 25 
test 26 10000000.05  == 10000000.10
  failed in test 26 
test 27 10000000.05  == 10000000.10
  failed in test 27 
test 30 99999999.99 == 100000000.00
  failed in test 30 
test 78 123.12345    == 123.12345
  1. z/OS default REXX
REXX370 3.48 01 May 1992
Default digits: 9
test 4 127 == 127.00
  failed in test 4
test 16 10000000.10  == 10000000.10
test 19 10000000.60  == 10000000.60
test 20 10000000.10  == 10000000.10
test 22 10000000.00  == 10000000.00
test 23 10000000.00  == 10000000.00
test 24 10000000.50  == 10000000.50
test 25 10000000.10  == 10000000.10
test 26 10000000.10  == 10000000.10
test 27 10000000.10  == 10000000.10
test 30 100000000.00 == 100000000.00
test 78 123.12345 == 123.12345
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
Changing digits to 30
test 4 127 == 127.00
  failed in test 4
test 16 10000000.05  == 10000000.10
  failed in test 16
test 19 10000000.55  == 10000000.60
  failed in test 19
test 20 10000000.05  == 10000000.10
  failed in test 20
test 22 10000000.04  == 10000000.00
  failed in test 22
test 23 10000000.04  == 10000000.00
  failed in test 23
test 24 10000000.45  == 10000000.50
  failed in test 24
test 25 10000000.05  == 10000000.10
  failed in test 25
test 26 10000000.05  == 10000000.10
  failed in test 26
test 27 10000000.05  == 10000000.10
  failed in test 27
test 30 99999999.99 == 100000000.00
  failed in test 30
test 78 123.12345    == 123.12345
  1. Brexx370 on tk4-
BREXX/370 V2R3M0 (Sep 30 2020)
Default digits: 30
test 4 127 == 127.00
  failed in test 4
test 16 10000000.04  == 10000000.10
  failed in test 16
test 19 10000000.54  == 10000000.60
  failed in test 19
test 20 10000000.05  == 10000000.10
  failed in test 20
test 22 10000000.03  == 10000000.00
  failed in test 22
test 23 10000000.04  == 10000000.00
  failed in test 23
test 24 10000000.44  == 10000000.50
  failed in test 24
test 25 10000000.04  == 10000000.10
  failed in test 25
test 26 10000000.04  == 10000000.10
  failed in test 26
test 27 10000000.04  == 10000000.10
  failed in test 27
test 30 99999999.99 == 100000000.00
  failed in test 30
test 78 123.12345 == 123.123450000000014
  failed in test 78
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
Changing digits to 30
test 4 127 == 127.00
  failed in test 4
test 16 10000000.04  == 10000000.10
  failed in test 16
test 19 10000000.54  == 10000000.60
  failed in test 19
test 20 10000000.05  == 10000000.10
  failed in test 20
test 22 10000000.03  == 10000000.00
  failed in test 22
test 23 10000000.04  == 10000000.00
  failed in test 23
test 24 10000000.44  == 10000000.50
  failed in test 24
test 25 10000000.04  == 10000000.10
  failed in test 25
test 26 10000000.04  == 10000000.10
  failed in test 26
test 27 10000000.04  == 10000000.10
  failed in test 27
test 30 99999999.99 == 100000000.00
  failed in test 30
test 78 123.12345    == 123.123450000000008
  failed in test 78

On brexx I created a second script to force DIGITS to 9:

/* REXX */                                                              
parse version v                                                         
say v                                                                   
say "=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-"
say "Changing digits to 9"                                              
NUMERIC DIGITS 9                                                        
say "DIGITS" digits()                                                   
say "test 4" trunc(127.2) "==" 127.00                                   
if trunc(127.2) \== 127.00 then do                                      
   say '  failed in test 4 '                                            
  rc = 8                                                                
end                                                                     
say "test 16" trunc(10000000.05,2) " ==" 10000000.10                    
if trunc(10000000.05,2) \== 10000000.10 then do                         
   say '  failed in test 16 '                                           
  rc = 8                                                                
end                                                                     
say "test 19" trunc(10000000.55,2) " ==" 10000000.60                    
if trunc(10000000.55,2) \== 10000000.60 then do                         
   say '  failed in test 19 '                                           
  rc = 8                                                                
end                                                                     
say "test 20" trunc(10000000.055,2) " ==" 10000000.10                   
if trunc(10000000.055,2) \== 10000000.10 then do                        
   say '  failed in test 20 '                                           
  rc = 8                                                                
end                                                                     
say "test 22" trunc(10000000.04,2) ' ==' 10000000.00                    
if trunc(10000000.04,2) \== 10000000.00 then do                         
   say '  failed in test 22 '                                           
  rc = 8                                                                
end                                                                     
say "test 23" trunc(10000000.045,2) " ==" 10000000.00                   
if trunc(10000000.045,2) \== 10000000.00 then do                        
   say '  failed in test 23 '                                           
  rc = 8                                                                
end                                                                     
say "test 24" trunc(10000000.45,2) " ==" 10000000.50                    
if trunc(10000000.45,2) \== 10000000.50 then do                         
   say '  failed in test 24 '                                           
  rc = 8                                             
end                                                  
say "test 25" trunc(10000000.05,2) " ==" 10000000.10 
if trunc(10000000.05,2) \== 10000000.10 then do      
   say '  failed in test 25 '                        
  rc = 8                                             
end                                                  
say "test 26" trunc(10000000.05,2) " ==" 10000000.10 
if trunc(10000000.05,2) \== 10000000.10 then do      
   say '  failed in test 26 '                        
  rc = 8                                             
end                                                  
say "test 27" trunc(10000000.05,2) " ==" 10000000.10 
if trunc(10000000.05,2) \== 10000000.10 then do      
   say '  failed in test 27 '                        
  rc = 8                                             
end                                                  
say "test 30" trunc(99999999.99,2) "==" 100000000.00 
if trunc(99999999.99,2) \== 100000000.00 then do     
   say '  failed in test 30 '                        
  rc = 8                                             
end                                                  
say "test 78" trunc(123.12345,5) "   ==" 123.12345   
if trunc(123.12345,5) \== 123.12345 then do          
   say '  failed in test 78 '                        
  rc = 8                                             
end                                                  

with the results:

BREXX/370 V2R3M0 (Sep 30 2020)
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
Changing digits to 9
DIGITS 9
test 4 127 == 127.00
  failed in test 4
test 16 10000000.04  == 10000000.10
  failed in test 16
test 19 10000000.54  == 10000000.60
  failed in test 19
test 20 10000000.05  == 10000000.10
  failed in test 20
test 22 10000000.03  == 10000000.00
  failed in test 22
test 23 10000000.04  == 10000000.00
  failed in test 23
test 24 10000000.44  == 10000000.50
  failed in test 24
test 25 10000000.04  == 10000000.10
  failed in test 25
test 26 10000000.04  == 10000000.10
  failed in test 26
test 27 10000000.04  == 10000000.10
  failed in test 27
test 30 99999999.99 == 100000000.00
  failed in test 30
test 78 123.12345    == 123.12345
mainframed commented 4 years ago

I noticed some weirdness as well with test 78 and replicated it with the following:

say 0 digits()          
say 1 123.12345         
say 2 trunc(123.12345,5)
say 3 123.12345         
NUMERIC DIGITS 30       
say 4 123.12345         
say 5 trunc(123.12345,5)
say 6 123.12345         
NUMERIC DIGITS 9        
say 7 123.12345         
say 8 trunc(123.12345,5)
say 9 123.12345         

Output:

0 30
1 123.12345
2 123.12345
3 123.123450000000014
4 123.123450000000014
5 123.12345
6 123.123450000000008
7 123.123450000000008
8 123.12345
9 123.12345
mgrossmann commented 4 years ago

We have found improper behavior when converting to real numbers. This error may have an effect on quite a lot of different places. Since this is most likely a problem in the compiler, we contacted Jason.

Peter-Jacob commented 4 years ago

Maybe I misinterpreted the "rounding" concept of TRUNC. In my view, the rounding should occur to the last decimal digit before truncating the number. Obviously this is not the case, it looks like it is meant to be rounded to the number based on the number of DIGITS setting, and then cut off. If this is true, there is little we can do, as we don't support setting of DIGITS in the same way.