github.com/enetx/g@v1.0.80/float.go (about)

     1  package g
     2  
     3  import (
     4  	"encoding/binary"
     5  	"fmt"
     6  	"math"
     7  	"math/big"
     8  	"math/bits"
     9  	"strconv"
    10  
    11  	"github.com/enetx/g/cmp"
    12  	"github.com/enetx/g/pkg/constraints"
    13  )
    14  
    15  // NewFloat creates a new Float with the provided value.
    16  func NewFloat[T constraints.Float | constraints.Integer](float T) Float { return Float(float) }
    17  
    18  // Bytes returns the Float as a byte slice.
    19  func (f Float) Bytes() Bytes {
    20  	buffer := make([]byte, 8)
    21  	binary.BigEndian.PutUint64(buffer, f.ToUInt64())
    22  
    23  	return buffer[bits.LeadingZeros64(f.ToUInt64())>>3:]
    24  }
    25  
    26  // Min returns the minimum of two Floats.
    27  func (f Float) Min(b ...Float) Float { return cmp.Min(append(b, f)...) }
    28  
    29  // Max returns the maximum of two Floats.
    30  func (f Float) Max(b ...Float) Float { return cmp.Max(append(b, f)...) }
    31  
    32  // Abs returns the absolute value of the Float.
    33  func (f Float) Abs() Float { return Float(math.Abs(f.Std())) }
    34  
    35  // Add adds two Floats and returns the result.
    36  func (f Float) Add(b Float) Float { return f + b }
    37  
    38  // ToBigFloat returns the Float as a *big.Float.
    39  func (f Float) ToBigFloat() *big.Float { return big.NewFloat(f.Std()) }
    40  
    41  // Cmp compares two Floats and returns an cmp.Ordering.
    42  func (f Float) Cmp(b Float) cmp.Ordering { return cmp.Cmp(f, b) }
    43  
    44  // Div divides two Floats and returns the result.
    45  func (f Float) Div(b Float) Float { return f / b }
    46  
    47  // IsZero checks if the Float is 0.
    48  func (f Float) IsZero() bool { return f.Eq(0) }
    49  
    50  // Eq checks if two Floats are equal.
    51  func (f Float) Eq(b Float) bool { return f.Cmp(b).IsEq() }
    52  
    53  // Std returns the Float as a float64.
    54  func (f Float) Std() float64 { return float64(f) }
    55  
    56  // Gt checks if the Float is greater than the specified Float.
    57  func (f Float) Gt(b Float) bool { return f.Cmp(b).IsGt() }
    58  
    59  // ToInt returns the Float as an Int.
    60  func (f Float) ToInt() Int { return Int(f) }
    61  
    62  // ToString returns the Float as an String.
    63  func (f Float) ToString() String { return String(strconv.FormatFloat(f.Std(), 'f', -1, 64)) }
    64  
    65  // Lt checks if the Float is less than the specified Float.
    66  func (f Float) Lt(b Float) bool { return f.Cmp(b).IsLt() }
    67  
    68  // Mul multiplies two Floats and returns the result.
    69  func (f Float) Mul(b Float) Float { return f * b }
    70  
    71  // Ne checks if two Floats are not equal.
    72  func (f Float) Ne(b Float) bool { return !f.Eq(b) }
    73  
    74  // Round rounds the Float to the nearest integer and returns the result as an Int.
    75  func (f Float) Round() Int {
    76  	if f >= 0 {
    77  		return Int(f + 0.5)
    78  	}
    79  
    80  	return Int(f - 0.5)
    81  }
    82  
    83  // RoundDecimal rounds the Float value to the specified number of decimal places.
    84  //
    85  // The function takes the number of decimal places (precision) as an argument and returns a new
    86  // Float value rounded to that number of decimals. This is achieved by multiplying the Float
    87  // value by a power of 10 equal to the desired precision, rounding the result, and then dividing
    88  // the rounded result by the same power of 10.
    89  //
    90  // Parameters:
    91  //
    92  // - precision (Int): The number of decimal places to round the Float value to.
    93  //
    94  // Returns:
    95  //
    96  // - Float: A new Float value rounded to the specified number of decimal places.
    97  //
    98  // Example usage:
    99  //
   100  //	f := g.Float(3.14159)
   101  //	rounded := f.RoundDecimal(2) // rounded will be 3.14
   102  func (f Float) RoundDecimal(precision Int) Float {
   103  	if precision < 0 {
   104  		return f
   105  	}
   106  
   107  	mult := 1
   108  	for range precision {
   109  		mult *= 10
   110  	}
   111  
   112  	result := f * Float(mult)
   113  	if result >= 0 {
   114  		result += 0.5
   115  	} else {
   116  		result -= 0.5
   117  	}
   118  
   119  	return Float(int(result)) / Float(mult)
   120  }
   121  
   122  // Sub subtracts two Floats and returns the result.
   123  func (f Float) Sub(b Float) Float { return f - b }
   124  
   125  // ToUInt64 returns the Float as a uint64.
   126  func (f Float) ToUInt64() uint64 { return math.Float64bits(f.Std()) }
   127  
   128  // AsFloat32 returns the Float as a float32.
   129  func (f Float) AsFloat32() float32 { return float32(f) }
   130  
   131  // Print prints the value of the Float to the standard output (console)
   132  // and returns the Float unchanged.
   133  func (f Float) Print() Float { fmt.Println(f); return f }